2016-07-06 39 views
0

這是一個最小的玩具示例,顯示我遇到的問題。DataTrigger和Storyboard只能執行一次,與聲明的順序有關嗎?

我使用MVVM創建了一個WPF應用程序。主ViewModel包含一個ItemViewModel s的集合。每個項目具有枚舉Position屬性,其值可以是值LeftCenterRight

我想根據它的Position屬性來定位集合中的每個項目。當這個值改變時,它需要動畫到新的位置。

這裏是虛擬機:

ItemViewModel.cs

public enum Position 
{ 
    Left, Center, Right 
} 

public class ItemViewModel : BindableBase 
{ 
    private string _myData; 
    private Position _position; 

    public string MyData 
    { 
     get { return _myData; } set { SetProperty(ref _myData, value); } 
    } 
    public Position Position 
    { 
     get { return _position; } set { SetProperty(ref _position, value); } 
    } 
} 

ViewModel.cs

public class ViewModel 
{ 
    public ObservableCollection<ItemViewModel> Items { get; set; } 
    public DelegateCommand Switch { get; } 

    public ViewModel() 
    { 
     Switch = new DelegateCommand(DoSwitch); 

     Items = new ObservableCollection<ItemViewModel>(); 
     Items.Add(new ItemViewModel() { MyData = "I1", Position = Position.Left }); 
     Items.Add(new ItemViewModel() { MyData = "I2", Position = Position.Right }); 
    } 

    private void DoSwitch() 
    { 
     var p = Items[0].Position; 
     Items[0].Position = Items[1].Position; 
     Items[1].Position = p; 
    } 
} 

我結合ViewModel.ItemsItemsControl,然後使用DataTrigger小號開始Storyboard這是基於Position屬性動畫邊距的s。

MainWindow.xaml

<Window.DataContext> 
    <local:ViewModel/> 
</Window.DataContext> 

<StackPanel> 

    <Button Content="Switch" Command="{Binding Switch}"/> 

    <ItemsControl ItemsSource="{Binding Items}"> 

     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <Label Content="{Binding MyData}"/> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 

     <ItemsControl.ItemContainerStyle> 
      <Style TargetType="ContentPresenter"> 
       <Setter Property="Margin" Value="50,0,0,0"/> 

       <Style.Triggers> 
        <DataTrigger Binding="{Binding Position}" Value="{x:Static local:Position.Left}"> 
         <DataTrigger.EnterActions> 
          <BeginStoryboard> 
           <Storyboard> 
            <ThicknessAnimation Storyboard.TargetProperty="Margin" 
                Duration="0:0:1" 
                To="0"/> 
           </Storyboard> 
          </BeginStoryboard> 
         </DataTrigger.EnterActions> 
        </DataTrigger> 

        <DataTrigger Binding="{Binding Position}" Value="{x:Static local:Position.Center}"> 
         <DataTrigger.EnterActions> 
          <BeginStoryboard> 
           <Storyboard> 
            <ThicknessAnimation Storyboard.TargetProperty="Margin" 
                Duration="0:0:1" 
                To="100,0,0,0"/> 
           </Storyboard> 
          </BeginStoryboard> 
         </DataTrigger.EnterActions> 
        </DataTrigger> 

        <DataTrigger Binding="{Binding Position}" Value="{x:Static local:Position.Right}"> 
         <DataTrigger.EnterActions> 
          <BeginStoryboard> 
           <Storyboard> 
            <ThicknessAnimation Storyboard.TargetProperty="Margin" 
                Duration="0:0:1" 
                To="200,0,0,0"/> 
           </Storyboard> 
          </BeginStoryboard> 
         </DataTrigger.EnterActions> 
        </DataTrigger> 
       </Style.Triggers> 
      </Style> 
     </ItemsControl.ItemContainerStyle> 
    </ItemsControl> 
</StackPanel> 

的問題

點擊 「切換」 按鈕爲動畫左邊到右邊的項目,反之亦然。然而,它只是對右邊的動畫(從LeftCenterRight或從CenterRight)。它在左側沒有動畫(RightCenterLeftCenterLeft)。

更奇怪的是,如果我顛倒XAML中的DataTrigger聲明的順序,那麼它只會在另一個方向(從右到左)動畫。

如果我刪除動畫並在觸發器中將邊距設置爲Setter,那麼它將按預期工作。另外,如果我將FillBehavior設置爲Stop,那麼它會每次向左或向右動畫,但會「捕捉」回默認值。

它看起來好像系統只執行一個Storyboard,後面在XAML聲明中比當前的「活動」DataTrigger

爲什麼會發生這種情況?我該如何解決它?

回答

0

https://msdn.microsoft.com/en-us/library/system.windows.media.animation.timeline.fillbehavior(VS.95).aspx

填充行爲可以造成一種錯覺,一個屬性是在運行時不能設置的,如果你不小心意外停止動畫。試圖在代碼中更改來自填充動畫的動畫值將在填充動畫停止之前似乎無效。

例如:改變你的動畫(警告:所有的人),以

<ThicknessAnimation Storyboard.TargetProperty="Margin" Duration="0:0:1" To="0" 
        FillBehavior="Stop" /> 

事情一切正常。但它會重置動畫之間的值。

+0

感謝代碼猴子。正如問題中提到的那樣,我們注意到將填充行爲設置爲「停止」將會「修復」這個問題,但這不是一個真正的解決方案,因爲動畫的全部要點是讓應用看起來很漂亮,並從一個位置跳到另一個(即'FillBehavior =「Stop」')不是一個可行的解決方案。 =(另外,由於缺省的切換行爲是'SnapshotAndReplace',所以現有的故事板不需要被停止,所以一次只能有一個動畫在一個項目上運行。 –