如何等待状态更改过渡在Silverlight 4中完成?
我需要更改控件的状态,然后执行一些操作。具体而言,我想在隐藏控件之前运行动画。我愿做这样的事情:如何等待状态更改过渡在Silverlight 4中完成?
VisualStateManager.GoToState(control, "Hidden", true); // wait until the transition animation is finished
ParentControl.Children.Remove(control);
的问题是过渡动画是异步运行,从而控制从动画开始后立即可视化树移除。
那么如何等待动画完成?
您可以将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)
{
}
}
}
这是我想到的唯一解决方案。但对我来说这似乎不是很好,很干净。 :-(另一方面,如果没有其他解决方案,我将别无选择,谢谢 – gius 2010-09-06 20:06:02
但是如果我们使用自定义控件呢?在这种情况下,无法在xaml中添加处理程序。 – 2011-07-23 20:47:50
@ dains解决方案适用于这种情况。 – 2011-07-23 20:53:10
的正确方法处理这个问题的方法是监听VisualStateGroup上的CurrentStateChanged事件,但根据我的经验,它最多不可靠,最坏的情况是坏的。
第二个选项是在你的故事板钩完成的事件,但该选项有其自身的缺陷。在某些情况下,可视化状态管理器会在内部生成动画,因此您设置的完成事件不会被调用。
事实上,这是有可能附上完成处理程序代码:从这个线程
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的根UserControl(在VisualStateManager.GoToState中使用)和LayoutRoot获取实际的VisualStateGroup集合使用单独的依赖项属性,但有些恼人。
这也适用于WPF。感谢帖子,这正是我一直在寻找的! – 2011-03-29 15:39:21
这可以在MVVM中完成吗? – user20358 2011-12-14 12:48:23