Как дождаться перехода изменения состояния в Silverlight 4? - PullRequest
12 голосов
/ 06 сентября 2010

Мне нужно изменить состояние элемента управления, а затем выполнить какое-либо действие.Если быть точным, я хочу запустить анимацию до того, как элемент управления будет скрыт.Я хотел бы сделать что-то вроде этого:

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

Проблема в том, что анимация перехода запускается асинхронно и, таким образом, элемент управления удаляется из визуального дерева сразу после запуска анимации.* Так как же мне ждать окончания анимации?

Ответы [ 3 ]

14 голосов
/ 06 сентября 2010

Вы можете присоединить обработчик событий Storyboard.Completed к раскадровке или прикрепить обработчик событий VisualStateGroup.CurrentStateChanged к 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)
    {

    }
}

}

3 голосов
/ 17 марта 2011

Фактически возможно прикрепить обработчик Completed в коде:

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;
        }
    }
}

Пример из этой темы: http://forums.silverlight.net/forums/p/38027/276746.aspx

Работать для меня в живом проекте, используя также присоединенное поведение!Немного раздражает, что мне пришлось использовать отдельные свойства зависимостей для корневого UserControl (для использования в VisualStateManager.GoToState) и LayoutRoot для получения фактической коллекции VisualStateGroup.

3 голосов
/ 07 сентября 2010

Правильный способ решения этой проблемы - прослушивание события CurrentStateChanged в VisualStateGroup, но, по моему опыту, в лучшем случае оно ненадежно, а в худшем - неисправно.

Второй вариант - перехватить событие «Завершено» на вашей раскадровке, но эта опция имеет свои подводные камни. В некоторых случаях менеджер визуальных состояний генерирует внутреннюю анимацию, поэтому заданное вами событие Completed не будет вызываться.

...