VisualStateManager Class
Definition
Important
Some information relates to prerelease product that may be substantially modified before it’s released. Microsoft makes no warranties, express or implied, with respect to the information provided here.
Manages visual states and the logic for transitions between visual states for controls. Also provides the attached property support for VisualStateManager.VisualStateGroups
, which is how you define visual states in XAML for a control template.
/// [Windows.Foundation.Metadata.ContractVersion(Microsoft.UI.Xaml.WinUIContract, 65536)]
/// [Windows.Foundation.Metadata.MarshalingBehavior(Windows.Foundation.Metadata.MarshalingType.Agile)]
/// [Windows.Foundation.Metadata.Threading(Windows.Foundation.Metadata.ThreadingModel.Both)]
class VisualStateManager : DependencyObject
[Windows.Foundation.Metadata.ContractVersion(typeof(Microsoft.UI.Xaml.WinUIContract), 65536)]
[Windows.Foundation.Metadata.MarshalingBehavior(Windows.Foundation.Metadata.MarshalingType.Agile)]
[Windows.Foundation.Metadata.Threading(Windows.Foundation.Metadata.ThreadingModel.Both)]
public class VisualStateManager : DependencyObject
Public Class VisualStateManager
Inherits DependencyObject
- Inheritance
- Attributes
Examples
This example shows how to use the VisualStateManager.VisualStateGroups
XAML attached property. Note how there is otherwise no "VisualStateManager" tag defined. Conceptually, VisualStateManager.VisualStateGroups
contains the visual states for a control, as an immediate child tag of the template root in a control template.
The particular set of visual states contains one VisualStateGroup, called "CommonStates", which defines the "PointerOver" and "Normal" VisualState objects. When the user puts the pointer over the Button, the Grid changes from green to red in .5 seconds. When the user moves the pointer away from the button, the Grid immediately changes back to green.
<ControlTemplate TargetType="Button">
<Grid >
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<!--Take one half second to transition to the PointerOver state.-->
<VisualTransition To="PointerOver"
GeneratedDuration="0:0:0.5"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal" />
<!--Change the SolidColorBrush, ButtonBrush, to red when the
Pointer is over the button.-->
<VisualState x:Name="PointerOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="ButtonBrush"
Storyboard.TargetProperty="Color" To="Red" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.Background>
<SolidColorBrush x:Name="ButtonBrush" Color="Green"/>
</Grid.Background>
</Grid>
</ControlTemplate>
<common:LayoutAwarePage>
<Grid>
...
<VisualStateManager.VisualStateGroups>
<!-- Visual states reflect the application's window size -->
<VisualStateGroup>
<VisualState x:Name="DefaultLayout">
<Storyboard>
</Storyboard>
</VisualState>
<VisualState x:Name="Below768Layout">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Margin)"
Storyboard.TargetName="ContentRoot">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Thickness>20,20,20,20</Thickness>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.HorizontalAlignment)"
Storyboard.TargetName="FooterPanel">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<HorizontalAlignment>Left</HorizontalAlignment>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</common:LayoutAwarePage>
The next snippet is code to go along with the XAML, showing how an app might detect the app window width and use that info to call the appropriate visual state.
String state = (Window.Current.Bounds.Width > 768) ? "DefaultLayout" : "Below768Layout";
VisualStateManager.GoToState(this, state, false); // 'this' is the LayoutAwarePage, scope is page code-behind
Remarks
VisualStateManager
supports two important features for control authors, and for app developers who are applying a custom template to a control:
- Control authors or app developers add VisualStateGroup object elements to the root element of a control template definition in XAML, using the
VisualStateManager.VisualStateGroups
attached property. Within aVisualStateGroup
element, each VisualState represents a discrete visual state of a control. EachVisualState
has a name that is representative of a UI state that can be changed by the user, or changed by control logic. AVisualState
consists mainly of a Storyboard. ThisStoryboard
targets individual dependency property value changes that should be applied whenever the control is in that visual state. - Control authors or app developers transition between these states by calling the static GoToState method of
VisualStateManager
. Control authors do this whenever the control logic handles events that indicate a change of state, or control logic initiates a state change by itself. It's more common for control definition code to do this rather than app code, so that all the possible visual states and their transitions and trigger conditions are there by default for app code, and the logic is encapsulated by the control.
Most developers will use just two of the VisualStateManager
APIs: VisualStateManager.VisualStateGroups
, and GoToState, as described above. The remaining APIs are all for extension support and creating a custom VisualStateManager
. For more info see the "Custom VisualStateManager" section in this topic.
When you edit copies of styles as enabled by the XAML design surface of Microsoft Visual Studio, the visual states from the default template are defined in the XAML you are editing. Make sure you don't delete these states or change their names, because the control logic is expecting that these visual states exist in the template.
In addition to the visual states, the visual state model also includes transitions. Transitions are animation actions controlled by a Storyboard that occur between each visual state when the state is changed. The transition can be defined differently for each combination of starting state and ending state as defined by your control's set of visual states. Transitions are defined by the Transitions property of VisualStateGroup
, in XAML using property element syntax. Most default control templates don't define transitions. In absence of specifically defined transitions, the transitions between states happen instantaneously (zero-duration). For more info, see VisualTransition.
Custom VisualStateManager
If you want to implement your own logic for transitions between states (an advanced scenario), you can create a class that inherits from VisualStateManager
. Follow these guidelines:
- The derived class should override the protected GoToStateCore method. Any instance of the custom
VisualStateManager
uses this Core logic when its GoToState method is called. - To reference your custom
VisualStateManager
class, set the value of theVisualStateManager.CustomVisualStateManager
attached property on the root element of a ControlTemplate where you want to use the customVisualStateManager
class behavior, alongside theVisualStateManager.VisualStateGroups
attached property usage that defines the visual states for the template. You typically create an instance of the customVisualStateManager
class through default XAML construction in Application.Resources. Then theVisualStateManager.CustomVisualStateManager
attached property is set using a {StaticResource} markup extension reference to the key of the customVisualStateManager
resource.
That's the basic requirements for creating and using a custom VisualStateManager
. You also can choose to override a few more behaviors:
- Override RaiseCurrentStateChanged to control when the CurrentStateChanged event is fired by a VisualStateGroup being managed by the
VisualStateManager
. - Override RaiseCurrentStateChanging to control when the CurrentStateChanging event is fired by a VisualStateGroup being managed by the
VisualStateManager
. - Override or overload the constructor if your custom class needs additional information to initialize with.
All the other API (CustomVisualStateManagerProperty, GetCustomVisualStateManager, GetVisualStateGroups, SetCustomVisualStateManager) are infrastructure for attached property support, and you don't need to call them or do anything with them.
Visual states for elements that aren't controls
Visual states are sometimes useful for scenarios where you want to change the state of some area of UI that's not immediately a Control subclass. You can't do this directly because the control parameter of the GoToState method requires a Control
subclass, which refers to the object that the VisualStateManager acts upon. Page is a Control
subclass, and it's fairly rare that you'd be showing UI in a context where you don't have a Page
, or your Window.Content root isn't a Control
subclass. We recommend you define a custom UserControl to either be the Window.Content
root or be a container for other content you want to apply states to (such as a Panel). Then you can call GoToState on your UserControl
and apply states regardless of whether the rest of the content is a Control
. For example you could apply visual states to UI that otherwise consists of just a SwapChainPanel so long as you placed that within your UserControl
and declared named states that apply to the properties of the parent UserControl
or of the named SwapChainPanel
part of the template.
XAML attached properties
VisualStateManager
is the host service class for several XAML attached properties.
In order to support XAML processor access to the attached properties, and also to expose equivalent get and set operations to code, each XAML attached property has a pair of Get
and Set
accessor methods. Another way to get or set the value in code is to use the dependency property system, calling either GetValue or SetValue and passing the identifier field as the dependency property identifier.
Attached Property | Description |
---|---|
VisualStateGroups | Gets the collection of VisualStateGroup elements that are defined by a root element of a template definition. A control typically defines this as part of its template.
When getting this property in code, use GetVisualStateGroups. This returns a collection object, which you can add items to. This parallels the XAML processing behavior of any child elements of a VisualStateManager.VisualStateGroups property element usage. Because there is no public dependency property identifier for this particular attached property, you cannot use GetValue to get this attached property value, you always have to use GetVisualStateGroups. |
CustomVisualStateManager | Gets or sets the custom VisualStateManager object that handles transitions between the states of a control.
This attached property is only needed for cases where you want to use a custom implementation class to handle your app's visual state changes, rather than the default VisualStateManager class implemented by the Windows Runtime. If you don't intend to use a custom implementation, you don't need to set this property. |
Constructors
VisualStateManager() |
Initializes a new instance of the VisualStateManager class. |
Properties
CustomVisualStateManagerProperty |
Identifies the VisualStateManager.CustomVisualStateManager dependency property. |
Dispatcher |
Always returns |
DispatcherQueue |
Gets the |
Attached Properties
CustomVisualStateManager |
Gets or sets the custom VisualStateManager object that handles transitions between the states of a control. |