How to wait for state changing transition to finish in Silverlight 4?
Asked Answered
C

3

12

I need to change state of a control and then do some action. To be specific, I want to run an animation before a control is hidden. I would like to do something like that:

VisualStateManager.GoToState(control, "Hidden", true); // wait until the transition animation is finished
ParentControl.Children.Remove(control);

The problem is that the transition animation is run asynchronously and thus the control is removed from the visual tree right after the animation is started.

So how do I wait for the animation to finish?

Costermonger answered 6/9, 2010 at 17:56 Comment(2)
This works in WPF too. Thanks for the post, this is exactly what I was looking for!Sag
any way this can be done in MVVM ?Dingle
O
14

You can attach a Storyboard.Completed event handler to the Storyboard or attach a VisualStateGroup.CurrentStateChanged event handler to the VisualStateGroup:

<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
x:Class="SilverlightApplication7.MainPage"
Width="640" Height="480">

<Grid x:Name="LayoutRoot" Background="White">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="VisualStateGroup" >
            <VisualState x:Name="Hidden">
                <Storyboard Completed="OnHidden">
                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="rectangle" d:IsOptimized="True"/>
                </Storyboard>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <Rectangle x:Name="rectangle" Fill="#FFF4F4F5" HorizontalAlignment="Left" Height="136" Margin="48,72,0,0" Opacity="0" Stroke="Black" VerticalAlignment="Top" Width="208"/>
</Grid>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightApplication7
{
public partial class MainPage : UserControl
{
    public MainPage()
    {
        // Required to initialize variables
        InitializeComponent();

        this.Loaded += new RoutedEventHandler(MainPage_Loaded);
    }

    void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        VisualStateManager.GoToState(this, "Hidden", true);
    }

    private void OnHidden(object storyboard, EventArgs args)
    {

    }
}

}

Osmium answered 6/9, 2010 at 18:39 Comment(2)
This was the only solution that came to my mind. But it does not seem very nice and clean to me. :-( On the other hand, if there is no other solution, I'll have no choice. Thank you.Costermonger
But what if we are using Custom control? In that case it is not possible to add handler into xaml.Infundibulum
D
4

It is in fact possible to attach the Completed handler in code:

Collection<VisualStateGroup> grps = (Collection<VisualStateGroup>)VisualStateManager.GetVisualStateGroups(this.LayoutRoot);
foreach (VisualStateGroup grp in grps) {
    Collection<VisualState> states = (Collection<VisualState>)grp.States;
    foreach (VisualState state in states) {
        switch (state.Name) {
            case "Intro":
            state.Storyboard.Completed += new EventHandler(Intro_Completed);break;
        }
    }
}

Example from this thread: http://forums.silverlight.net/forums/p/38027/276746.aspx

Working for me in live project using attached Behavior too! Slightly annoying though that I had to use separate dependency properties for the root UserControl (to use in VisualStateManager.GoToState) and the LayoutRoot to get the actual VisualStateGroup collection.

Deianira answered 17/3, 2011 at 12:55 Comment(0)
L
3

The correct way of handling this issue would be listening to CurrentStateChanged event on VisualStateGroup, but from my experience it is not reliable at best and broken at worst.

Second option is to hook Completed event on your Storyboard, but this option got pitfalls of its own. In some cases visual state manager generates animations internally, so Completed event you set will not get called.

Lebkuchen answered 6/9, 2010 at 20:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.