9 Stimmen

Überschreiben Schaltfläche Hintergrund in WPF auf Aero

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.

2voto

Thomas Levesque Punkte 277723

Die Standardvorlage für Button verwendet eine ButtonChrome , die ihre eigene Zeichnung ausführt. Wenn Sie das standardmäßige Erscheinungsbild vollständig loswerden wollen, müssen Sie eine eigene Vorlage definieren, ohne die ButtonChrome . Ich weiß, dass es sich mühsam anhört, aber Sie müssen es nur einmal machen: Sie können Ihren benutzerdefinierten Stil in ein Ressourcen-Wörterbuch aufnehmen und einfach auf ihn verweisen mit StaticResource . Beachten Sie, dass Sie den Stil auch auf alle Schaltflächen in Ihrer Anwendung anwenden können, indem Sie {x:Type Button} als Schlüssel für den Stil ( x:Key Attribut)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X