2010-11-05 1 views
7

Ich hatte eine schnelle Google und einen kurzen Blick auf StackOverflow, konnte aber niemanden finden, der auf dieses Problem gestoßen wäre.Wie zeichnen Sie Formen oder Linien innerhalb einer WPF-Schaltfläche, die so groß ist wie das Steuerelement, ohne dass die Schaltfläche für immer erweitert wird?

Ich möchte eine Schließen-Schaltfläche mit einem kleinen X darin erstellen. Mit der Schließen-Schaltfläche können Sie ein- und ausblenden, wenn Sie über das Objekt mit der Maus zeigen, die Farbe ändern, wenn Sie mit der Maus darüber fahren, und die übliche WPF-Lieblichkeit. Unterm Strich scheint es nicht so schwierig zu sein, aber ich stoße auf eines der merkwürdigsten Probleme, bevor ich dieses Stadium erreicht habe.

Hier ist meine XAML-Stil für die Schaltfläche:

<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> 

Und ich meine Taste erstellen, ebenso wie ein Test, wie folgt aus:

<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> 

Und hier ist, wo alles schief geht. Wenn Sie die Anwendung ausführen, wird die Schaltfläche unendlich, ein Pixel nach dem anderen, horizontal und vertikal erweitert, bis sie die Höhe des Fensters erreicht.

Jetzt kann ich verstehen, warum das passiert: die Linien gehen tatsächlich eine Einheit über die Breite und Höhe des Grids hinaus, was das Grid um eine Einheit erweitert, dann gibt es ein Relayout, die Datenbindung bewirkt, dass die Linien neu gezeichnet werden, Ad infinitum.

Also, um zu versuchen, damit umzugehen, entschied ich mich, ein in das Raster zu setzen, aber dann, egal was ich mit HorizontalAlignment und VerticalAlignment mache, komme ich sowohl mit dem Canvas als auch dem Grid mit null Breite und Höhe bedeutet, dass ich mein Kreuz nicht bekomme, was sehr irritierend ist. Wenn ich an die ActualWidth- und ActualHeight-Eigenschaften der Schaltfläche binde, habe ich am Ende ein X, bei dem die obere linke Ecke in der Mitte der Schaltfläche zentriert ist.

Hat jemand irgendeine Idee, was ich tun kann, um das zu beheben? Ich wäre sehr dankbar für irgendwelche Hinweise - WPF ist immer noch ein ziemlich neues Biest für mich.

Danke!

Antwort

15

vorschlagen Sie sollten nicht nur auf Bindungen greifen müssen, um das Layout zu tun.Wie Sie gesehen haben, funktionieren Bindings und Layout-Systeme nicht zusammen (ich denke, Databinding hat Vorrang vor Layout, aber in Ihrem Fall verursacht Layout eine andere Datenbindung)

Sie sollten in der Lage sein, ziemlich nett auszusehen dehnbar X mit nur einem Pfad:

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

Wenn Sie es Skala mit Knopfgröße statt strecken wollen (Skala scheinbare Strichbreite betrifft), dann benutzen Sie einfach eine ViewBox

+0

Gute Antwort. Wenn sich der Button jedoch in einem StackPanel befindet (wie im Beispiel), scheint Ihnen das nur einen Punkt in der Mitte des Buttons zu geben, es sei denn, Sie geben Breite –

+0

wahr, es wird skaliert, um den Anforderungen des Containers zu entsprechen . Die minimale und minimale Höhe in dem Beispiel wäre ausreichend, nein? –

+1

Aus irgendeinem Grund, nein. Es ist nur ein Punkt in der Mitte, aber wenn Sie beispielsweise Width = "2" und immer noch MinWidth = "50" setzen, erhalten Sie das Kreuz. –

2

Statt zu binden, würde ich vorschlagen, die Stretch und Margin oder Padding Eigenschaften verwenden, wie in der folgenden

<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> 

aktualisieren

Also das Problem mit Ihrem Beispiel zu sein scheint die minimale Höhe & Breite. Wenn Sie nicht nur Höhe & Breite verwenden können, würde ich so etwas wie die folgenden

<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

Vielen Dank allen . Robs Lösung mit der Viewbox erwies sich als die Antwort. Die Schaltfläche verhält sich einwandfrei, auch wenn ich die Attribute MidWidth und MinHeight aus der Button-Deklaration in MainWindow.xaml entferne.

Hier ist meine geändert anzeige:

<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> 

Nochmals vielen Dank für alle Anregungen!