2010-09-06 57 views
12

我需要更改控件的狀態,然後執行一些操作。具體而言,我想在隱藏控件之前運行動畫。我願做這樣的事情:如何等待狀態更改過渡在Silverlight 4中完成?

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

的問題是過渡動畫是異步運行,從而控制從動畫開始後立即可視化樹移除。

那麼如何等待動畫完成?

+0

這也適用於WPF。感謝帖子,這正是我一直在尋找的! – 2011-03-29 15:39:21

+0

這可以在MVVM中完成嗎? – user20358 2011-12-14 12:48:23

回答

14

您可以將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) 
    { 

    } 
} 

}

+0

這是我想到的唯一解決方案。但對我來說這似乎不是很好,很乾淨。 :-(另一方面,如果沒有其他解決方案,我將別無選擇,謝謝 – gius 2010-09-06 20:06:02

+0

但是如果我們使用自定義控件呢?在這種情況下,無法在xaml中添加處理程序。 – 2011-07-23 20:47:50

+0

@ dains解決方案適用於這種情況。 – 2011-07-23 20:53:10

3

的正確方法處理這個問題的方法是監聽VisualStateGroup上的CurrentStateChanged事件,但根據我的經驗,它最多不可靠,最壞的情況是壞的。

第二個選項是在你的故事板鉤完成的事件,但該選項有其自身的缺陷。在某些情況下,可視化狀態管理器會在內部生成動畫,因此您設置的完成事件不會被調用。

2

事實上,這是有可能附上完成處理程序代碼:從這個線程

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集合使用單獨的依賴項屬性,但有些惱人。