Dotneteers.net
All for .net, .net for all!

No more magic strings with VisualStateManager.GoToState

This may come as no surprise for some, but only today have I discovered a way to get rid of the magic strings when changing states with the VisualStateManager.GoToState method. The way Microsoft and many others were explaining the Visual State Manager is via a sample code like this:

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

 

Unfortunately, this introduces a magic string, namely “statename”. The problem with the magic string here is that it creates a tight contract between the XAML (where the states are usually defined) and the code behind. It is very easy to mistype the name of the state in either place. Also, if the state is renamed by the designer in Blend, you get no compiler warnings or even runtime exceptions to point out the error.

Here is a small XAML sample using the Visual States to move an ellipse to the right of a Grid:

   1:      <Grid x:Name="LayoutRoot"  Background="LightBlue">
   2:          <VisualStateManager.VisualStateGroups>
   3:              <VisualStateGroup x:Name="SG1">
   4:                  <VisualStateGroup.Transitions>
   5:                      <VisualTransition GeneratedDuration="00:00:01">
   6:                          <VisualTransition.GeneratedEasingFunction>
   7:                              <ElasticEase EasingMode="EaseOut"/>
   8:                          </VisualTransition.GeneratedEasingFunction>
   9:                      </VisualTransition>
  10:                  </VisualStateGroup.Transitions>
  11:                  <VisualState x:Name="SG1Normal"/>
  12:                  <VisualState x:Name="SG1EllipseRight" >
  13:                      <Storyboard>
  14:                          <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="ellipse" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
  15:                              <EasingDoubleKeyFrame KeyTime="00:00:00" Value="320"/>
  16:                          </DoubleAnimationUsingKeyFrames>
  17:                      </Storyboard>
  18:                  </VisualState>
  19:              </VisualStateGroup>
  20:          </VisualStateManager.VisualStateGroups>
  21:          <Ellipse x:Name="ellipse" Fill="Red" Stroke="Black" 
  22:                   Height="116" HorizontalAlignment="Left" Margin="50,98,0,0" 
  23:                   VerticalAlignment="Top" Width="235" RenderTransformOrigin="0.5,0.5" >
  24:              <Ellipse.RenderTransform>
  25:                  <TransformGroup>
  26:                      <ScaleTransform/>
  27:                      <SkewTransform/>
  28:                      <RotateTransform/>
  29:                      <TranslateTransform/>
  30:                  </TransformGroup>
  31:              </Ellipse.RenderTransform>
  32:          </Ellipse>
  33:      </Grid>

 

The key to my “discovery” is realizing that the VisualState elements have an x:Name attribute, and therefore fields get generated for them in the codebehind. So, instead of

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

We can write:

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

Now, if the state gets renamed, at least we get a compiler error, and there is no way that you can mistype the state name.

Another advantage of accessing the states by name is that now it is easy to find when a state transition animation ends (like the one above). Just use the VisualState.Storyboard.Completed event:

SG1EllipseRight.Storyboard.Completed += (sender, args) => 
      MessageBox.Show("Ellipse move finished!");

That is two big problems that I had with Visual States solved. Now if only I could get the current state somehow…

Here  is a little bonus:

You can also create some extension methods on VisualState as it may fit your way of thinking better:

    public static class VisualStateHelper
    {
        public static void Activate(this VisualState state, Control control, bool useTransitions)
        {
            VisualStateManager.GoToState(control, state.Name, useTransitions);
        }

        public static void Activate(this VisualState state, Control control)
        {
            state.Activate(control, true);
        }
    }

Now, to activate the SG1EllipseRight state above, all you have to write is:

SG1EllipseRight.Activate(this)

That’s all, folks!


Posted Dec 29 2009, 11:00 PM by vbandi

Comments

vbandi wrote re: No more magic strings with VisualStateManager.GoToState
on Tue, Dec 29 2009 23:13

Sorry for the lack of color coding, community server kills my styles :(

Twitter Trackbacks for No more magic strings with VisualStateManager.GoToState - VBandi's blog - Dotneteers.net [dotneteers.net] on Topsy.com wrote Twitter Trackbacks for No more magic strings with VisualStateManager.GoToState - VBandi's blog - Dotneteers.net [dotneteers.net] on Topsy.com
on Wed, Dec 30 2009 10:52

Pingback from  Twitter Trackbacks for                 No more magic strings with VisualStateManager.GoToState - VBandi's blog - Dotneteers.net         [dotneteers.net]        on Topsy.com

Dew Drop – December 30, 2009 | Alvin Ashcraft's Morning Dew wrote Dew Drop &#8211; December 30, 2009 | Alvin Ashcraft&#039;s Morning Dew
on Wed, Dec 30 2009 14:30

Pingback from  Dew Drop – December 30, 2009 | Alvin Ashcraft's Morning Dew

Albo d'Oro NBA | Houston Rockets NBA Announcer wrote Albo d&#039;Oro NBA | Houston Rockets NBA Announcer
on Thu, Dec 31 2009 10:44

Pingback from  Albo d'Oro NBA | Houston Rockets NBA Announcer

Albo d'Oro NBA | Houston Rockets NBA Announcer wrote Albo d&#039;Oro NBA | Houston Rockets NBA Announcer
on Thu, Dec 31 2009 10:44

Pingback from  Albo d'Oro NBA | Houston Rockets NBA Announcer

Twitted by SilverlightNews wrote Twitted by SilverlightNews
on Thu, Dec 31 2009 19:10

Pingback from  Twitted by SilverlightNews

uberVU - social comments wrote Social comments and analytics for this post
on Thu, Dec 31 2009 23:06

This post was mentioned on Twitter by vbandi: @JustinAngel btw, I found a solution for one of our earlier discussions. http://is.gd/5GoNP

Sergey wrote re: No more magic strings with VisualStateManager.GoToState
on Sat, Mar 20 2010 12:10

It seems like it doesn't work in cases when styles, states etc. defined in the resource dictionary and not directly in the window, or in the app.xaml.

vbandi wrote re: No more magic strings with VisualStateManager.GoToState
on Sat, Mar 20 2010 13:03

Sergey: Yes, you are correct. The above technique relies on the members generated for the codebehind, and no such members are generated for items defined in Resources