VisualStateManager - zeigt den Mouseover-Status an, wenn die Steuerung fokussiert ist

7

Ich erstelle eine WPF-Taste mit Windows 8 Styling (früher Metro).

Ich möchte, dass der fokussierte Zustand der Schaltfläche mit einem durchgehenden Hintergrund angezeigt wird. Wenn sich die Maus über dem Steuerelement befindet, möchte ich, dass der Hintergrund leicht dunkler wird, um den visuellen Hinweis zu erzeugen, dass die Schaltfläche angeklickt werden kann.

Leider funktioniert der XAML, den ich unten geschrieben habe, nicht. Der fokussierte Zustand wird korrekt angezeigt, aber wenn sich die Maus über dem Steuerelement befindet, wird der Hintergrund nicht so abgedunkelt, wie ich es möchte.

%Vor%     
Cameron Peters 31.01.2013, 18:38
quelle

2 Antworten

20

Ich habe jetzt deinen Code getestet. Sie haben hier ein paar Probleme im Spiel. Aber das Hauptproblem ist, dass ein WPF-Steuerelement immer nur in einem Visual State einer bestimmten State Group sein kann. Und in Fällen wie Sie hier sind, wo die Kontrolle sein kann Sowohl als auch moused-over muss sich WPF entscheiden, welchen Staat sie anwenden soll (sie kann nicht beide Staaten anwenden, da sie in derselben State Group sind). In diesem Fall bleibt es nur im fokussierten Zustand und sendet es nicht in den MouseOver-Zustand.

Ein Steuerelement kann in mehreren Zuständen sein, wenn sich jeder dieser Zustände in verschiedenen Statusgruppen befindet. Von dieser Dokumentation :

  

Jede VisualStateGroup enthält eine Sammlung von VisualState-Objekten, die sich gegenseitig ausschließen. Das heißt, das Steuerelement befindet sich immer in genau einem Zustand von in jeder VisualStateGroup.

Unser erster Schritt zur Korrektur dieses Codes besteht darin, die richtigen Statusgruppen einzubeziehen, die es der Schaltfläche ermöglichen, ihren fokussierten Zustand anzuzeigen und dann ihren MouseOver-Status anzuzeigen (andere Möglichkeiten können durch diese Änderung korrigiert werden, aber das ist die eine) Sie haben insbesondere bemerkt, dass Sie mit Ihrer bisherigen Vorgehensweise nicht zurecht gekommen sind.)

Um dies zu tun, müssen wir vorsichtig sein, unsere Staatsgruppen und (insbesondere) unsere Staatsnamen richtig zu benennen. Dies liegt daran, dass der interne Code der Button-Klasse wahrscheinlich einen Aufruf wie VisualStateManager.GoToState(this, "VerySpecificStateName", true); ausführt (ich habe den tatsächlichen Quellcode der Button-Klasse nicht überprüft, um dies zu überprüfen, aber benutzerdefinierte Steuerelemente geschrieben, die ich zum Initiieren der Statusänderungen benötigt habe) Ich weiß, dass es so etwas sein muss). Um eine Liste der Zustandsgruppen- und Zustandsnamen zu erhalten, die wir benötigen, könnten wir entweder Expression Blend verwenden, um eine Kopie der Kontrollvorlage zu bearbeiten (die die benötigten Zustände für uns auffüllen wird), oder sie finden < a href="http://msdn.microsoft.com/en-us/library/ms753328.aspx"> hier . Diese Dokumentation zeigt uns, dass wir eine Staatsgruppe namens "FocusStates" und zwei Staaten in der Gruppe "Focused" und "Unfocused" (zusammen mit anderen Staatsgruppen und Staaten) brauchen. Um zu veranschaulichen, wie die Button-Klasse ihre Statusänderungen durch diese spezifischen benannten Zustände einleitet, wenn Sie Ihren ursprünglichen Code ändern, indem Sie den Statusstatus "Focus" durch "MisspelledFocus" ersetzen, sehen Sie, dass Ihre Schaltfläche diesen niemals eingibt Zustand.

Wenn wir diese erste Änderung implementieren, könnten wir etwas wie:

haben %Vor%

Das löst das Problem etwas. Wenn Sie dies jedoch in Expression Blend sehen, werden Sie in den Überschriften der Statusgruppen eine Warnung bemerken:

Diese Warnung erhalten wir, weil wir den Wert eines identischen Eigenschaft / Objekt-Paares in mehr als einer Statusgruppe ändern - in diesem Fall die Eigenschaft "Color" des Objekts "BackgroundColor". Warum könnte das ein Problem sein? Aufgrund dessen, was ich vorher gesagt habe - die Tatsache, dass eine Kontrolle in mehreren Zuständen gleichzeitig sein kann, wenn diese Zustände in verschiedenen Staatsgruppen sind. Wenn also der Benutzer den Fokus der Schaltfläche angegeben hat und der Benutzer auch über die Schaltfläche geklickt hat, könnte es für WPF unklar sein, welche Animation angewendet werden soll, da beide Zustände sagen, dass dieselbe exakte Eigenschaft auf unterschiedliche Weise animiert wird.

Auch diese erste Änderung bringt uns nicht vollständig, was wir wollen. Wenn Sie versuchen, den Fokus der Schaltfläche zu aktivieren, bewegen Sie den Mauszeiger darüber, und zwar von "Normal" zu "Fokussiert" zu "MouseOver". Wenn Sie den Mauszeiger jetzt nicht mehr bewegen, werden Sie feststellen, dass die Schaltfläche nicht in den "Fokus" -Zustand zurückkehrt.

Es gibt mehrere Ansätze, die Sie verwenden könnten, um dieses Problem zu beheben und etwas zu erreichen, das dem entspricht, was Sie wollten, aber nur als Beispiel könnten wir so etwas tun. (Dies ist möglicherweise nicht die sauberste Implementierung dafür, aber es behebt das allgemeine Objekt / Eigenschaftsproblem.):

%Vor%

Jetzt werden Sie sehen, dass wir die Mehrdeutigkeit für WPF entfernt haben. Und wir sehen, dass es nun den Fall von Zustandsänderungen von "Normal" zu "Fokus" zu "MouseOver" und zurück zu "Focus" korrekt behandelt.

    
Jason Frank 01.02.2013, 19:23
quelle
1

Dies ist eine kleine Bearbeitung von Jasons Antwort. Es stellt sich heraus, dass sein Ansatz, der zwei ContentPresenter verwendet, die Funktion der Abkürzungstasten unterbricht. Ich habe eine kleine Anpassung vorgenommen ... die Shortcut-Tasten funktionieren jetzt, aber die Übergangsanimation ist nicht ganz so schön ...

%Vor%     
Cameron Peters 07.02.2013 23:47
quelle