2010-11-05 16 views
7

J'ai eu un rapide Google, et un coup d'oeil rapide autour de StackOverflow, mais je n'ai pas pu trouver quelqu'un d'autre qui rencontrerait ce problème.Comment dessiner une forme ou des lignes dans un bouton WPF de cette taille pour le contrôle sans provoquer le bouton pour étendre indéfiniment?

Je veux créer un bouton de fermeture avec un petit X dedans. Le bouton de fermeture fera des choses comme le fondu entrant et sortant lorsque vous survolez l'élément qui le contient, changez de couleur lorsque vous passez la souris, et toute la beauté habituelle de WPF. En fin de compte, il ne semble pas que cela devrait être si difficile, mais je suis confronté à l'un des problèmes les plus étranges que j'aie jamais connus jusqu'à présent.

Voici mon style XAML pour le bouton:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <Style x:Key="TabCloseButtonStyle" TargetType="{x:Type Button}"> 
     <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/> 
     <Setter Property="Background" Value="Transparent"/> 
     <Setter Property="Content"> 
      <Setter.Value> 
       <Grid> 
        <Line Stroke="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=Foreground}" 
          X1="0" 
          Y1="0" 
          X2="{Binding RelativeSource={RelativeSource AncestorType=Grid}, Path=ActualWidth, Mode=OneWay}" 
          Y2="{Binding RelativeSource={RelativeSource AncestorType=Grid}, Path=ActualHeight, Mode=OneWay}"/> 
        <Line Stroke="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=Foreground}" 
          X1="0" 
          Y1="{Binding RelativeSource={RelativeSource AncestorType=Grid}, Path=ActualHeight, Mode=OneWay}" 
          X2="{Binding RelativeSource={RelativeSource AncestorType=Grid}, Path=ActualWidth, Mode=OneWay}" 
          Y2="0"/> 
       </Grid> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</ResourceDictionary> 

Et je crée mon bouton, tout comme un test, comme celui-ci:

<Window x:Class="WpfTestApp.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="124" Width="569"> 
    <Grid Background="#2b3c59"> 
     <StackPanel Orientation="Horizontal"> 

      <!-- Other controls removed for clarity --> 

      <Button Style="{DynamicResource TabCloseButtonStyle}" 
        HorizontalAlignment="Center" 
        VerticalAlignment="Bottom" 
        Padding="2" 
        Margin="0, 10, 0, 0" 
        MinWidth="50" 
        MinHeight="50"></Button> 
     </StackPanel> 
    </Grid> 
</Window> 

Et voici où tout va terriblement mal. Lorsque vous exécutez l'application, le bouton se déplie à l'infini, un pixel à la fois, horizontalement et verticalement jusqu'à atteindre la hauteur de la fenêtre. Maintenant je peux comprendre pourquoi cela se produit: les Lignes vont en fait d'une unité au-delà de la largeur et de la hauteur de la Grille provoquant l'expansion de la Grille d'une unité, puis il y a un relai, À l'infini. Donc, pour essayer de gérer cela, j'ai décidé de mettre un dans la grille mais ensuite, peu importe ce que je fais avec HorizontalAlignment et VerticalAlignment, je me retrouve avec le Canvas et le Grid ayant zéro largeur et hauteur, qui signifie que je ne reçois pas ma croix, ce qui est énormément irritant. Si je lie aux propriétés ActualWidth et ActualHeight du bouton, je finis avec un X dont le coin supérieur gauche est centré sur le centre du bouton.

Quelqu'un at-il une idée de ce que je peux faire pour résoudre ce problème? Je serais extrêmement reconnaissant pour les pointeurs - WPF est toujours une bête plutôt nouvelle pour moi.

Merci!

Répondre

15

Vous ne devriez pas avoir à recourir à des liaisons juste pour faire la mise en page.Comme vous l'avez vu, les liaisons et les systèmes de mise en page ne fonctionnent pas de concert (je pense que la liaison de données est prioritaire sur la mise en page, mais dans votre cas, la mise en page provoque une autre liaison de données). , extensible X avec un simple chemin:

<Path Data="M0,0 L1,1 M0,1 L1,0" Stretch="Uniform" Stroke="Red" /> 

Si vous le souhaitez échelle avec la taille du bouton au lieu d'étirement (échelle affecte la largeur de course apparente), puis il suffit d'utiliser un ViewBox

+0

Bonne réponse. Cependant, si le bouton est dans un StackPanel (comme dans l'exemple) alors cela semble vous donner seulement un point au milieu du bouton, sauf si vous spécifiez la largeur –

+0

vrai, il va évoluer pour s'adapter à toutes les exigences de son conteneur . La minwidth et minheight dans l'exemple serait suffisant, non? –

+1

Pour une raison quelconque, non. C'est juste un point au milieu mais si vous définissez Width = "2" par exemple et encore MinWidth = "50" alors vous obtenez la croix. –

2

Au lieu de lier, je suggère d'utiliser Stretch et la marge ou propriétés Rembourrage, comme ce qui suit

<Grid Margin="2"> 
    <Line X1="0" Y1="0" Y2="1" X2="1" Stroke="Black" Stretch="Fill" /> 
    <Line Y1="1" X2="1" Stroke="Black" Stretch="Fill" /> 
</Grid> 

Mise à jour

Le problème avec votre exemple semble être la hauteur min & largeur. Si vous ne pouvez pas utiliser la hauteur & largeur, je vous suggère quelque chose comme le

suivant
<Grid MinHeight="{TemplateBinding MinHeight}" MinWidth="{TemplateBinding MinWidth}"> 
    <Line X1="0" Y1="0" Y2="1" X2="1" Stroke="Black" Stretch="Fill" /> 
    <Line Y1="1" X2="1" Stroke="Black" Stretch="Fill" /> 
</Grid> 
0

Merci à tous . La solution de Rob avec le Viewbox s'est révélée être la réponse. Le bouton se comporte parfaitement, même si je supprime les attributs MidWidth et MinHeight de la déclaration Button dans MainWindow.xaml.

Voici mon style modifié:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <Style x:Key="TabCloseButtonStyle" TargetType="{x:Type Button}"> 
     <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/> 
     <Setter Property="Background" Value="Transparent"/> 
     <Setter Property="Content"> 
     <Setter.Value> 
      <Grid> 
       <Viewbox> 
        <Path Data="M0,0 L10,10 M0,10 L10,0" 
          Stretch="Uniform" 
          Stroke="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=Foreground, Mode=OneWay}" /> 
       </Viewbox> 
      </Grid> 
     </Setter.Value> 
     </Setter> 
    </Style> 
</ResourceDictionary> 

Merci encore pour toutes les suggestions!