Der Wunsch ist also einfach, den Hintergrund einer Schaltfläche in Hellgrün, Grün, wenn der Mauszeiger darüber schwebt, und Dunkelgrün, wenn sie gedrückt wird, zu ändern. Die folgende XAML ist mein erster Versuch:
<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 Background="LightGreen">
Hello
<Button.Style>
<Style TargetType="Button">
<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>
Aber leider funktioniert das nicht. Wir sind erst 1/3 des Weges zum Ziel gekommen. Ja, die Schaltfläche wird hellgrün, aber sobald man mit dem Mauszeiger darüberfährt oder sie drückt, erhält man das Standard-Aero-Chrom für die jeweiligen Schaltflächenzustände. Da ich nicht aufgeben will, versuche ich die folgende Ausschweifung:
...
<Button xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
Background="LightGreen">
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="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding 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">
<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>
...
Jetzt haben wir die ganze verdammte Kontrollvorlage, die von Aero.NormalColor.xaml . Leider ändert sich dadurch nichts. Ich gehe dann dazu über, zwei Attribute zu entfernen ( RenderPressed
y RenderMouseOver
) aus dem Microsoft_Windows_Themes:ButtonChrome
Element. Dennoch gibt es keine Veränderung. Dann entferne ich die Einstellung des Button's Background
Attribut, so dass nur die Namespace-Deklaration für die Baugruppe PresentationFramework.Aero übrig bleibt:
...
<Button xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero">
Hello
...
Endlich haben wir einen Fortschritt. Wir sind von 1/3 der Anforderungen zu 2/3 des Weges gegangen, mit IsMouseOver und IsPressed arbeiten, aber keine hellgrünen Hintergrund während der Schaltfläche der normalen Zustand (der nicht über oder gedrückt Maus), da ich die Eigenschaft Hintergrund aus der Schaltfläche entfernt habe, um die anderen beiden Zustände zu erhalten, zu gelten und sichtbar sein. Nun, nach dieser verrückten XAML scheitert, um uns die LightGreen Hintergrund für den normalen Zustand der Schaltfläche zu erhalten, ändere ich den Stil, um die Hintergrundfarbe in dort auch zu werfen:
<Button xmlns...
<ControlTemplate...
...
</ControlTemplate>
<Button.Style>
<Style TargetType="Button">
<!-- ##### Normal state button background added ##### -->
<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 = "Background" Value="DarkGreen"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Endlich funktioniert es wie vorgesehen.
Bin ich verrückt, oder sind das (und mehr) die Reifen, die man mit einem Aero-Theme durchlaufen muss, um einfach die Hintergrundfarbe einer Schaltfläche in einigen ihrer verschiedenen Zustände (normal, mit dem Mauszeiger überfahren, gedrückt) zu ändern? Vielleicht wäre das Leben nicht so schlimm, wenn ich nicht das ganze verdammte ButtonTemplate einbinden müsste, nur um die beiden Attribute zu entfernen ( RenderMouseOver
y RenderPressed
) daraus.
Vielen Dank für jede Hilfe - ich bin mit meinem Latein am Ende.
Aktualisierung: Aber warte, das ist noch nicht alles. Anstatt die Attribute RenderMouseOver und RenderPressed aus der Steuervorlage zu entfernen, ändern Sie sie einfach von:
<Microsoft_Windows_Themes:ButtonChrome SnapsToDevicePixels="true" ...
RenderMouseOver="{TemplateBinding IsMouseOver}"
RenderPressed="{TemplateBinding IsPressed}" ...
zu:
<Microsoft_Windows_Themes:ButtonChrome SnapsToDevicePixels="true" ...
RenderMouseOver="{Binding IsMouseOver}"
RenderPressed="{Binding IsPressed}" ...
..., behebt auch das Problem (das Ignorieren der Stil-Trigger der Schaltfläche). Ich denke, die Wurzel des Problems ist, dass die Template-Bindings zur Kompilierzeit angewendet werden (aus Leistungsgründen), während reguläre Bindings zur Laufzeit angewendet werden. Aus diesem Grund werden die Bindungen aus den Style-Triggern der einzelnen Schaltflächen nicht verwendet, wenn Attribute Template-Bindungen verwenden (d. h., die IsMouseOver und IsPressed aus der ursprünglichen Vorlage werden stattdessen verwendet).
Nach all dem oben Gesagten ist hier das kanonische Beispiel für das Ändern des Hintergrunds einer Schaltfläche in Aero unter Beibehaltung der ursprünglichen Steuervorlage:
<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>
Dies setzt natürlich voraus, dass nur eine Schaltfläche so gestaltet ist, andernfalls können die Vorlage und der Stil irgendwo in einen Ressourcenbereich ausgelagert werden. Außerdem gibt es keinen Auslöser für den Standardzustand einer Schaltfläche, aber er kann dem obigen Beispiel leicht hinzugefügt werden (vergessen Sie nicht, das Attribut RenderDefaulted in der Steuerelementvorlage zu ändern, um Binding statt TemplateBinding zu verwenden).
Wenn jemand Vorschläge hat, wie man Überschreiben Sie die TemplateBinding mit Binding für nur die beiden Attribute in der Steuervorlage, die geändert werden müssen, ohne Wiederholung der gesamten Chrome-Definition aus der aero xaml Großhandel, ich bin ganz Ohr.