Sunday, May 15, 2011

Visual State Manager - New Features in WPF 4.0



Visual state manager introduced as new feature in WPF4 but the same feature was available in Silverlight since long time. In this post i explained some basics about Visual State Manager.


What is Visual State Manager in WPF?

Visual State Manager is used to change appearance of control based on Visual State. Visual States Manager can be defined inside Control Template. Visual State Manager manages different states of control. You can customize the appearance of control according to its visual state. Visual State Manager contains Visual State Groups and inside Visual State Groups you can add Visual States. Visual State contains Storyboard and can be used to animate control on state change. Triggers in WPF are also used to change the appearance of control but it changes appearance based on properties of control (for eg. IsMouseOver, IsDefault, IsEnabled etc.).

When you specify Visual State Manager in Control Template it uses specified Visual States to change appearance of control. You can also specify Transition duration while changing form one Visual State to another. You can easily apply visual states to any control using Microsoft Expression Blend.  

Visual Sates and Parts of Control

Visual State Manager supports parts (As per MSDN, Parts are named elements in Control Templates) and visual states model (As per MSDN, a visual state represents the appearance of the control under a given set of circumstances). 

Each control has its own states and all states are grouped into state groups. As per below figure, Button has two State Group one is Common States and another is Focus States. Now common states has four states Normal, MouseOver, Pressed, disabled and Focus State has two states unfocused and focused. So at a time button has only one state from each group.



Simple example using Visual State Manager

<Window x:Class="WpfApplication1.VisualStateManagerClass"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="VisualStateManager" Height="150" Width="150">
    <Window.Resources>
    <Style x:Key="MyButton" TargetType="{x:Type Button}">
    <Setter Property="Template">
    <Setter.Value>
    <ControlTemplate TargetType="{x:Type Button}">
    <Grid>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
                <VisualStateGroup.Transitions>
                    <VisualTransition GeneratedDuration="0:0:0.5"/>
                </VisualStateGroup.Transitions>
                <VisualState x:Name="Normal"/>
                <VisualState x:Name="MouseOver">
                    <Storyboard>
                        <ColorAnimationUsingKeyFrames
                            Storyboard.TargetProperty=
                              "(Shape.Fill).(SolidColorBrush.Color)"
                            Storyboard.TargetName="ellipse">
                            <EasingColorKeyFrame KeyTime="0"
                              Value="#FF20F50E"/>
                        </ColorAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="Pressed">
                    <Storyboard>
                        <ColorAnimationUsingKeyFrames
                            Storyboard.TargetProperty=
                              "(Shape.Fill).(SolidColorBrush.Color)"
                            Storyboard.TargetName="ellipse">
                            <EasingColorKeyFrame KeyTime="0"
                              Value="#FFF5230E"/>
                        </ColorAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="Disabled"/>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <Ellipse x:Name="ellipse" Fill="#FF0E0EF5" Stroke="Black"/>
        <ContentPresenter
  HorizontalAlignment=
       "{TemplateBinding HorizontalContentAlignment}"
         RecognizesAccessKey="True"
         SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
         VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
    </Grid>
    </ControlTemplate>
    </Setter.Value>
    </Setter>
    </Style>
    </Window.Resources>
    <Grid>
        <Button Content="Click Me!"
                Style="{StaticResource MyButton}"
                Height="100" Width="100" />
    </Grid>
</Window>


Output

Normal State















MouseOver State















Pressed State















Hope, you like this post and have better understanding about Visual State Manager.


Please post your suggestion/queries/feedback in comments if any.

1 comment: