2010-12-13 7 views
0

Ich möchte die Hintergrundfarbe einer Schaltfläche in seinen normalen, Mouse-Over und gedrückten Status in verschiedenen Schattierungen von Grün ändern. Ich bin gezwungen, den folgenden grotesk ausführlichen Button.Template zu meinem Knopf hinzuzufügen, so dass ich die Attribute ändern kann, um Binding anstelle von TemplateBinding zu verwenden, so dass meine Auslöser (in der Button.Style) tatsächlich wirksam werden, anstatt wegen der Kompilierung ignoriert zu werden Zeit Natur von TemplateBinding. Gibt es überhaupt eine Möglichkeit, diese beiden Attribute für ein Aero-Thema sauberer zu überschreiben als die gesamte Vorlagenbindung in ihrer Gesamtheit zu wiederholen? XAML folgt:Wie ändern Sie TemplateBindings in Bindungen in einer Steuerelementvorlage Steuerelement, ohne die gesamte Steuerelementvorlage zu wiederholen

<Window x:Class="ButtonMouseOver.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
    <Button> 
     Hello 
     <Button.Template> 
     <ControlTemplate TargetType="{x:Type Button}"> 
      <Microsoft_Windows_Themes:ButtonChrome SnapsToDevicePixels="true" 
      x:Name="Chrome" Background="{TemplateBinding Background}" 
      BorderBrush="{TemplateBinding BorderBrush}" RenderDefaulted="{TemplateBinding IsDefaulted}" 
      RenderMouseOver="{Binding IsMouseOver}" RenderPressed="{Binding IsPressed}" 
      > 
      <ContentPresenter Margin="{TemplateBinding Padding}" 
              VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
              RecognizesAccessKey="True" 
              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
      </Microsoft_Windows_Themes:ButtonChrome> 
     </ControlTemplate> 
     </Button.Template> 
     <Button.Style> 
     <Style TargetType="Button"> 
      <Setter Property="Background" Value="LightGreen"/> 
      <Style.Triggers> 
      <Trigger Property="IsMouseOver" Value="true"> 
       <Setter Property = "Background" Value="Green"/> 
      </Trigger> 
      <Trigger Property="IsPressed" Value="true"> 
       <Setter Property = "Foreground" Value="DarkGreen"/> 
      </Trigger> 
      </Style.Triggers> 
     </Style> 
     </Button.Style> 
    </Button> 
    </Grid> 
</Window> 

Wichtiger Hinweis: Die Steuervorlage nur für die Aero-Design notwendig ist. Bei anderen Themen wird nur der Button.Style alleine ausgeführt.

+0

Ich verstehe nicht, warum Sie nicht einen Stil erstellen, um damit umzugehen und es einfach auf jede Schaltfläche anzuwenden, wie Sie für richtig halten? Ich vermisse das Stück, das diesem Verhalten widersteht ...? Scheint wie eine Standard-Button-Stil für mich ... –

+0

Der Teil, der dieses Verhalten widersteht, ist der Aero-Chrom. Ich habe eine Notiz hinzugefügt, um diese Tatsache hervorzuheben. –

Antwort

1

Das Beste, was ich mir vorstellen kann, ist das Hinzufügen eines angehängten Verhaltens, das dies durch Reflexion deaktiviert, sobald der Button geladen ist. Ich weiß nicht, wenn Sie diese besser gefällt als neu Vorlage, aber Sie müssen nicht PresentationFramework.Aero und ihre wiederverwendbaren

<Button behaviors:DisableButtonChromeBehavior.DisableButtonChrome="True" 
     ...> 
    <Button.Style> 
     <Style TargetType="Button"> 
      <Setter Property="Background" Value="LightGreen"/> 
      <Style.Triggers> 
       <Trigger Property="IsMouseOver" Value="true"> 
        <Setter Property="Background" Value="Green"/> 
       </Trigger> 
       <Trigger Property="IsPressed" Value="true"> 
        <Setter Property="Foreground" Value="DarkGreen"/> 
       </Trigger> 
      </Style.Triggers> 
     </Style> 
    </Button.Style> 
</Button> 

Die DisableButtonChromeBehavior

public static class DisableButtonChromeBehavior 
{ 
    public static readonly DependencyProperty DisableButtonChromeProperty = 
     DependencyProperty.RegisterAttached 
     (
      "DisableButtonChrome", 
      typeof(bool), 
      typeof(DisableButtonChromeBehavior), 
      new UIPropertyMetadata(false, OnDisableButtonChromePropertyChanged) 
     ); 
    public static bool GetDisableButtonChrome(DependencyObject obj) 
    { 
     return (bool)obj.GetValue(DisableButtonChromeProperty); 
    } 
    public static void SetDisableButtonChrome(DependencyObject obj, bool value) 
    { 
     obj.SetValue(DisableButtonChromeProperty, value); 
    } 
    private static void OnDisableButtonChromePropertyChanged(DependencyObject dpo, 
                  DependencyPropertyChangedEventArgs e) 
    { 
     Button button = dpo as Button; 
     if (button != null) 
     { 
      if ((bool)e.NewValue == true) 
      { 
       button.Loaded += OnButtonLoaded; 
      } 
      else 
      { 
       button.Loaded -= OnButtonLoaded; 
      } 
     } 
    } 
    private static void OnButtonLoaded(object sender, RoutedEventArgs e) 
    { 
     Button button = sender as Button; 
     Action action =() => 
      { 
       object buttonChrome = VisualTreeHelper.GetChild(button, 0); 
       Type type = buttonChrome.GetType(); 
       PropertyInfo propertyInfo = type.GetProperty("RenderMouseOver"); 
       if (propertyInfo != null) 
       { 
        propertyInfo.SetValue(buttonChrome, false, null); 
        propertyInfo = type.GetProperty("RenderPressed"); 
        propertyInfo.SetValue(buttonChrome, false, null); 
        propertyInfo = type.GetProperty("RenderDefaulted"); 
        propertyInfo.SetValue(buttonChrome, false, null); 
       } 
      }; 
     button.Dispatcher.BeginInvoke(action, DispatcherPriority.ContextIdle); 
    } 
} 

umfassen Update
Es gibt auch die kürzere nicht wiederverwendbare Weise, nur dies in Code hinter sich.

private void Button_Loaded(object sender, RoutedEventArgs e) 
{ 
    Button button = sender as Button; 
    object buttonChrome = VisualTreeHelper.GetChild(button, 0); 
    PropertyInfo renderMouseOverInfo = buttonChrome.GetType().GetProperty("RenderMouseOver"); 
    if (renderMouseOverInfo != null) 
    { 
     renderMouseOverInfo.SetValue(buttonChrome, false, null); 
    } 
} 

Oder (wenn Sie nicht Aero einschließlich nichts dagegen haben)

<Button ...> 
    <Button.Resources> 
     <Style TargetType="Microsoft_Windows_Themes:ButtonChrome"> 
      <EventSetter Event="Loaded" Handler="ButtonChrome_Loaded"/> 
     </Style> 
    </Button.Resources> 

void ButtonChrome_Loaded(object sender, RoutedEventArgs e) 
{ 
    ButtonChrome buttonChrome = sender as ButtonChrome; 
    if (buttonChrome != null) 
    { 
     buttonChrome.RenderMouseOver = false; 
     buttonChrome.RenderPressed = false; 
    } 
} 

Other than that, ich glaube, Sie haben keine andere outs als die Lösung, die Sie sich darauf (Re-Templat) .

+0

Whoa, obwohl ich sicher bin, dass das funktionieren würde, ist es sogar "verbose" als die XAML Aufnahme aller Chrom ... –

+0

Sie sind endgültige Lösung sieht gut aus! Schade, dass es nicht über XAML gemacht werden kann ... –

0

Wenn Sie den Stil wechseln den Hintergrund verwenden möchten, können Sie nicht explizit die Background-Eigenschaft festgelegt, wie Sie hier getan haben:

<Button Background="LightGreen"> 

Dies wird außer Kraft setzen jede Art, die Sie festlegen. Versuchen Sie stattdessen:

<Button.Style> 
    <Style TargetType="Button"> 
     <Setter Property = "Background" Value="LightGreen"/> 
     <Style.Triggers> 
     <Trigger Property="IsMouseOver" Value="true"> 
      <Setter Property = "Background" Value="Green"/> 
     </Trigger> 
     <Trigger Property="IsPressed" Value="true"> 
      <Setter Property = "Foreground" Value="DarkGreen"/> 
     </Trigger> 
     </Style.Triggers> 
    </Style> 
    </Button.Style> 

Dies sollte es so machen, können Sie loswerden der Schaltfläche Vorlage erhalten, es sei denn, Sie daran, mehr tun möchten.

Wenn Sie von der Aero Unsinn bekommen möchte zu befreien, um die Vorlage ersetzen, wie so:

<Button.Template> 
    <ControlTemplate TargetType="{x:Type Button}"> 
     <Border SnapsToDevicePixels="true" x:Name="Chrome" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}"> 
     <ContentPresenter Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
     </Border> 
    </ControlTemplate> 
    </Button.Template> 

Der Nachteil hier ist, wenn Sie Aero nicht möchten, müssen Sie nichts davon bekommen und Sie müssen von vorne anfangen mit Ihrer Vorlage.

+0

Meine Entschuldigungen, ich habe diese Aufsicht korrigiert. Ihre Lösung funktioniert jedoch nicht für das Aero-Design und die Steuerelementvorlage ist weiterhin erforderlich. –

+0

@Michael: Möchten Sie das Aero-Design für alle Betriebssysteme verwenden? Wenn dies der Fall ist, gibt es keine andere Möglichkeit, Aero zu erzwingen, als die Schablone außer Kraft zu setzen und die Aero-Ressourcen spezifisch zu verwenden, da WPF das Gefühl des aktuellen Windows-Betriebssystems nutzt. – poindexter12

+0

Nein, ich schaue mir gerade an, wie man, wenn Aero benutzt wird, die Hintergrundfarbe eines Knopfes auf effektive Weise ändert. Das einfache Einstellen des Button-Stils (für Aero) funktioniert nicht. –

Verwandte Themen