Access storyboard from VisualStateManager/ access VisualState in code (programmatically)
As you might have found out (or not) you can’t access VisualStates by their name in code/programmatically. Setting a VisualState in code is also a bit of a hassle compared to declaring it in XAML, and then of course you can’t use Blend. If you try to access a named storyboard that is wrapped in a VisualState, then you will get a Null Reference Exception. Since I had a hard time finding a decent solution I would like to share with you two ways of solving this issue, and if you have any other solutions/can improve this code, please email or twitter me! I love feedback on my code, I have only been doing this for less than a year so my coding skills are not the best (yet) but it would be a shame not to share my solutions just because of of that :) So here you go, two ways:
The quick and dirty not so readable, my first solution to this issue
[sourcecode language=“csharp”]
//What I don’t like here is the use of ‘magic numbers’
var storyboard = VisualStateManager.GetVisualStateGroups(this.LayoutRoot)[1].States[2].Storyboard;
//
[/sourcecode]
How I do it (at the moment)
[sourcecode language=“csharp”]
//What I do like here is the readability, and since I will be using this a lot extensions seem like the best way to go about it
public sealed partial class GroupedItemsPage : Trainer.Common.LayoutAwarePage
{
void SomeMethod()
{
var storyboard = VisualStateManager.GetVisualStateGroups(this.LayoutRoot).Get(“TapStates”).States.Get(“PointerDown”).Storyboard;
}
}
public static class StateExtensions
{
public static VisualStateGroup Get(this IList stateGroups, string name)
{
return stateGroups.Single(x => x.Name == name);
}
public static VisualState Get(this IList<VisualState> stateGroups, string name)
{
return stateGroups.Single(x => x.Name == name);
}
}
[/sourcecode]
The VisualStates, wrapped in a Grid named “LayoutRoot”
[sourcecode language=“XML”]
<VisualStateManager.VisualStateGroups>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemGridView" Storyboard.TargetProperty="Padding">
<DiscreteObjectKeyFrame KeyTime="0" Value="96,0,10,56"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Snapped">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedBackButtonStyle}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="pageTitle" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedPageHeaderTextStyle}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemGridView" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="TapStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerDown">
<Storyboard x:Name="PressedAnimation">
<PointerDownThemeAnimation TargetName="LogEntry" />
</Storyboard>
</VisualState>
<VisualState x:Name="PointerUp">
<Storyboard x:Name="ReleasedAnimation">
<PointerUpThemeAnimation TargetName="LogEntry" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
[/sourcecode]
Comments
Last modified on 2012-06-28