0

In my xaml file I have:

<Grid x:Name="LayoutRoot"...>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="WebformSizeState">
<VisualState x:Name="MaximizedSizeState">
     <Storyboard x:Name="MaximizeSizeStory">
         <DoubleAnimation Duration="0:0:0.3" To="-120" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="WebpageContainer"/>
     </Storyboard>
</VisualState>
...

<ec:DataTriggerBehavior Value="2" Binding="{Binding WebpageSizeState, Converter={StaticResource EnumToIntegerConverter}}">
     <ec:GoToStateAction StateName="MaximizedSizeState"/>
</ec:DataTriggerBehavior>
...

The code works, as is. If the WebpageSizeState get the in value of 2 then the WebpageContainer moves up by 120.

I want to change To value of the DoubleAnimation of the Storyboard in the code behind file programmatically, but to do this I need to get the Storyboard (I assume).

Things I tried but failed:

Attempt 1

According to the MSDN documentation, direct access should work, but if I try to assign the value:

Storyboard maximizeSizeStory = MaximizeSizeStory;

then maximizeSizeStory is null and looking in the Watch window, MaximizeSizeStory is also null.

Attempt 2

Assigning a name to the DoubleAnimation and trying to access it directly:

<DoubleAnimation x:Name="MaximizeAnimation" ../>

This causes the app to crash with a null ref exception when the DataTrigger binding is changed in the ViewModel.

And oh yeah, the value in the code behind is null also.

Attempt 3

Finding the element using it's UID as done in this question: You cannot because UIElement and DependencyObject does not define a UID anymore.

And Storyboard isn't a UIElement, which I think is the reason why using FindName

Storyboard sb = this.FindName("MaximizeSizeStory") as Storyboard;

also returns null.

Attempt 4

Accessing it via a Key does not work because it's not defined in Page.Resources or in a dictionary.

And if you try do declare it in Page.Resources it gives error:

A property element cannot be the direct content of another property element. Nested properties are not supported: VisualStateManager.VisualStateGroups.


I'm at a loss, any ideas?

Community
  • 1
  • 1
Barnstokkr
  • 2,904
  • 1
  • 19
  • 34

1 Answers1

2

Here is one way (simplified example for clarity). Notice the use of the VisualStateManager.GetVisualStateGroups since the Storyboard is inside it:

enter image description here

    <Grid x:Name="LayoutRoot" Background="Transparent">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="MyGroups">
                <VisualState x:Name="MyStates">
                    <Storyboard x:Name="MyAnimation">
                        <ColorAnimation Duration="0" To="Yellow" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="rectangle" d:IsOptimized="True"/>
                    </Storyboard>
                </VisualState>
             </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    <Rectangle x:Name="rectangle" Height="50" Width="50" Fill="red"/>
<Button HorizontalAlignment="Center" VerticalAlignment="Bottom" Content="Click me"                Click="Button_Click" />    
</Grid>

And code for the button handler, where we actually access the storyboard:

    private void Button_Click(object sender, RoutedEventArgs e)
{
    var storyboard = VisualStateManager.GetVisualStateGroups(this.LayoutRoot)[0].States[0].Storyboard;
    storyboard.Begin();
}

Adding some extensions could make the code more readable and less prone to errors:

public sealed partial class SomePage
{
    void SomeMethod()
    {
        var storyboard = VisualStateManager.GetVisualStateGroups(this.LayoutRoot).Get("MyGroups").States.Get("MyStates").Storyboard;
    }
}

public static class StateExtensions
{
    public static VisualStateGroup Get(this IList<VisualStateGroup> 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);
    }
}
Iris Classon
  • 5,752
  • 3
  • 33
  • 52