Search code examples
wpfxamlcoding-style

Create custom VisualState in xaml and manually set it in CodeBehind


I have a TabItem style, which has VisualStates.

<VisualState x:Name="MouseOver"> 
<!-- Tab turns bronze when mouseover -->
</VisualState>

Now I want to have a custom visual state and manually set the state in codebehind instead of relying on the MouseOver event.

<VisualState x:Name="CustomVisualState">
<!-- this will be a storyboard to cause flashing -->
</VisualState> 

Then I need to set it in CodeBehind.

MyTabItem.VisualState = CustomVisualState.  //something like this

Solution

  • Have you tried VisualStateManager.GoToState

    Takes a Control, string with the custom state name and a bool flag for using transitions.

    Example Usage From msdn

    private void UpdateStates(bool useTransitions)
    {
        if (Value >= 0)
        {
            VisualStateManager.GoToState(this, "Positive", useTransitions);
        }
        else
        {
            VisualStateManager.GoToState(this, "Negative", useTransitions);
        }
    
        if (IsFocused)
        {
            VisualStateManager.GoToState(this, "Focused", useTransitions);
        }
        else
        {
            VisualStateManager.GoToState(this, "Unfocused", useTransitions);
        }
    }
    

    A slightly more complicated example usage from here

    Given this xaml

          <Grid x:Name="LayoutRoot"  Background="LightBlue">
              <VisualStateManager.VisualStateGroups>
                  <VisualStateGroup x:Name="SG1">
                      <VisualStateGroup.Transitions>
                          <VisualTransition GeneratedDuration="00:00:01">
                              <VisualTransition.GeneratedEasingFunction>
                                  <ElasticEase EasingMode="EaseOut"/>
                              </VisualTransition.GeneratedEasingFunction>
                          </VisualTransition>
                      </VisualStateGroup.Transitions>
                      <VisualState x:Name="SG1Normal"/>
                      <VisualState x:Name="SG1EllipseRight" >
                          <Storyboard>
                                <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="ellipse" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
                                  <EasingDoubleKeyFrame KeyTime="00:00:00" Value="320"/>
                              </DoubleAnimationUsingKeyFrames>
                          </Storyboard>
                      </VisualState>
                  </VisualStateGroup>
              </VisualStateManager.VisualStateGroups>
              <Ellipse x:Name="ellipse" Fill="Red" Stroke="Black" 
                       Height="116" HorizontalAlignment="Left" Margin="50,98,0,0" 
                       VerticalAlignment="Top" Width="235" RenderTransformOrigin="0.5,0.5" >
                  <Ellipse.RenderTransform>
                      <TransformGroup>
                          <ScaleTransform/>
                          <SkewTransform/>
                          <RotateTransform/>
                          <TranslateTransform/>
                      </TransformGroup>
                  </Ellipse.RenderTransform>
              </Ellipse>
          </Grid>
    

    Changing state can be done like so.

     VisualStateManager.GoToState(this, SG1EllipseRight.Name, true);
    

    Or alternatively

    VisualStateManager.GoToState(control, "SG1EllipseRight", true);