VisualStateManager — Anzeige des mouseover-Zustand, wenn das Steuerelement fokussiert ist
Erstelle ich ein WPF-button mit Windows 8 styling (ehemals metro).
Ich möchte, dass der fokussierte Zustand der Schaltfläche, um zu zeigen, mit einem soliden hintergrund. Wenn Sie die Maus über das Steuerelement, ich möchte th hintergrund zu verdunkeln, etwas zu erstellen, die visual cue, dass der button geklickt werden kann.
Leider die XAML-ich habe unten geschrieben, funktioniert nicht. Der fokussierte Zustand zeigt richtig, aber wenn sich die Maus über dem control, der hintergrund nicht dunkler als ich es haben möchte.
<Color x:Key="DoxCycleGreen">
#FF8DC63F
</Color>
<!-- Soft Interface : DoxCycle Green -->
<Color x:Key="DoxCycleGreenSoft">
#FFC0DC8F
</Color>
<Style x:Key="MetroButton" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="RootElement">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal" />
<VisualState Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundColor" Storyboard.TargetProperty="Color" To="{StaticResource DoxCycleGreen}" Duration="0:0:0.150" />
<ColorAnimation Storyboard.TargetName="FontColor" Storyboard.TargetProperty="Color" To="White" Duration="0:0:0.150" />
</Storyboard>
</VisualState>
<VisualState Name="Focused">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundColor" Storyboard.TargetProperty="Color" To="{StaticResource DoxCycleGreenSoft}" Duration="0:0:0.150" />
<ColorAnimation Storyboard.TargetName="FontColor" Storyboard.TargetProperty="Color" To="White" Duration="0:0:0.150" />
</Storyboard>
</VisualState>
<VisualState Name="Pressed">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundColor" Storyboard.TargetProperty="Color" To="Transparent" Duration="0:0:0.150" />
<ColorAnimation Storyboard.TargetName="FontColor" Storyboard.TargetProperty="Color" To="{StaticResource DoxCycleGreen}" Duration="0:0:0.150" />
</Storyboard>
</VisualState>
<VisualState Name="Disabled">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BorderColor" Storyboard.TargetProperty="Color" To="DarkGray" Duration="0:0:0.1" />
<ColorAnimation Storyboard.TargetName="FontColor" Storyboard.TargetProperty="Color" To="DarkGray" Duration="0:0:0.1" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Background="Transparent" >
<Border BorderThickness="1,1,1,1" Padding="2">
<Border.BorderBrush>
<SolidColorBrush x:Name="BorderColor" Color="{StaticResource DoxCycleGreen}"/>
</Border.BorderBrush>
<Border.Background>
<SolidColorBrush x:Name="BackgroundColor" Color="White"/>
</Border.Background>
<ContentPresenter
x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Content">
<TextBlock.Foreground>
<SolidColorBrush x:Name="FontColor" Color="{StaticResource DoxCycleGreen}"/>
</TextBlock.Foreground>
</ContentPresenter>
</Border>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
- Können Sie fügen Sie einige Klarstellungen? Werden Sie sagen, dass die MouseOver-Zustand wird nie angewendet, oder es wird nicht angewendet, wenn die Schaltfläche ist auch konzentriert?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich hab jetzt deinen code getestet. Sie haben ein paar Probleme hier im Spiel. Aber die Hauptproblem ist, dass ein WPF-Steuerelement kann nur in einem Visuellen Zustand zu einer bestimmten statusgruppe zu einer Zeit. Und in Fällen, wie Sie hier haben, wo die Kontrolle kann beide konzentriert und moused über, WPF zu stellen hat, die Wahl, welche Staat zu übernehmen (es kann nicht beides Staaten, da Sie in derselben statusgruppe). Also in diesem Fall ist es einfach, um es in den Fokussierten Zustand und nicht senden Sie es, um den MouseOver-Zustand.
Einer Kontrolle kann werden in mehrere Staaten, wenn jedes dieser Staaten in verschiedenen Statusgruppen. Von diese Dokumentation:
Also unser Erster Schritt zur Korrektur dieses Codes ist es, die richtigen Status-Gruppen, dass die Taste, um in der Lage sein zu zeigen, dass die Fokussierten Zustand, und zeigen dann seine MouseOver-Zustand (andere Möglichkeiten können korrigiert werden, indem diese zu ändern, aber das ist das einzige, das Sie bemerkte, insbesondere, dass Sie nicht mit Ihrem vorherigen Ansatz).
Um dies zu tun, müssen wir vorsichtig sein, um dem Namen unseres Staates-Gruppen und (vor allem) unsere state-Namen korrekt. Dies ist, weil der code innerhalb der Button-Klasse wahrscheinlich macht einen Anruf, wie
VisualStateManager.GoToState(this, "VerySpecificStateName", true);
(ich habe nicht geprüft, die eigentliche source-code der Klasse Button, um dies zu überprüfen, aber geschrieben hat benutzerdefinierte Steuerelemente, wo ich brauchte, um zu initiieren, der sich der Zustand ändert, ich weiß, es muss etwas in der Art). Um eine Liste der Status-Gruppe und Staat Namen, die wir brauchen, könnten wir entweder mit Expression Blend "Kopie Bearbeiten" des control template (das Auffüllen der benötigten Status für uns), oder Sie finden hier. Dass die Dokumentation uns zeigt, wir brauchen eine Staatliche Gruppe namens "FocusStates" und zwei Staaten, die Gruppe nennt sich "Konzentriert" und "Unkonzentriert" (zusammen mit anderen Gruppen und Staaten). Als ein beiseite, um zu zeigen, wie der Button-Klasse ist die Einleitung seinen Zustand ändert, indem diese bestimmte benannte Staaten, wenn Sie Ihre original-code durch ersetzen des "Focus", Zustand-name mit "MisspelledFocus", Sie werden sehen, dass Ihre Schaltfläche nie in diesem Staat.Umsetzung dieses erste änderung, wir könnten am Ende mit etwas wie:
Diese etwas löst das problem. Allerdings, wenn Sie sehen das Sie in Expression Blend werden Sie feststellen, eine Warnung in dem Zustand gruppenüberschriften:
Wir erhalten diese Warnung, weil wir ändern den Wert von einem identischen Grundstück/Objekt-pair-Mädchen in mehr als einem Staat Gruppe - in diesem Fall die "Farbe" - Eigenschaft des Objekts mit dem Namen "BackgroundColor". Warum könnte das ein Problem sein? Wegen dem, was ich vorhin gesagt - die Tatsache, dass ein Steuerelement kann in mehrere Staaten, wenn diese Staaten sind in den verschiedenen Statusgruppen. Also, wenn der Benutzer hat die Schaltfläche den Fokus und der Benutzer hat auch moused über die Schaltfläche, es könnte zweideutig sein zu WPF als um die animation zu wenden, da beide Staaten sagen, zu animieren, die gleiche Eigenschaft, jedoch in unterschiedlicher Weise.
Auch, diese erste änderung nicht ganz bekommen, was wir wollen. Wenn Sie versuchen, geben Sie die Fokus-Taste, dann bewegen Sie den Mauszeiger über es, es richtig, geht es von "Normalen", zu "Konzentriert", zu "MouseOver". Aber wenn Sie jetzt nicht weiter schweben, du wirst sehen, dass der Knopf nicht wieder in seine "Focus" - Zustand.
Gibt es mehrere Ansätze, die Sie verwenden können, um dieses problem zu lösen und etwas zu erreichen, ähnlich, was Sie wollte, aber nur als Beispiel, wir könnten so etwas tun. (Dies ist vielleicht nicht die sauberste Implementierung für diese, aber es behebt die common object/property-Ausgabe.):
Nun sehen Sie, dass wir entfernt haben, die die Mehrdeutigkeit für WPF. Und wir sehen, dass es behandelt nun den Fall, der Zustand ändert sich von "Normal" auf "Fokus" auf "MouseOver" und zurück zu "Focus" richtig.
Dies ist eine kleine änderung auf Jasons Antwort. Es stellt sich heraus, dass sein Ansatz mit zwei ContentPresenters bricht der Vorgang der short cut Tasten. Ich habe eine kleine Anpassung... die short cut Tasten funktionieren jetzt, aber der übergang animation nicht ganz so schön...