這是一個最小的玩具示例,顯示我遇到的問題。DataTrigger和Storyboard只能執行一次,與聲明的順序有關嗎?
我使用MVVM創建了一個WPF應用程序。主ViewModel包含一個ItemViewModel
s的集合。每個項目具有枚舉Position
屬性,其值可以是值Left
,Center
或Right
。
我想根據它的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.Items
到ItemsControl
,然後使用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>
的問題
點擊 「切換」 按鈕爲動畫左邊到右邊的項目,反之亦然。然而,它只是對右邊的動畫(從Left
到Center
或Right
或從Center
到Right
)。它在左側沒有動畫(Right
到Center
或Left
或Center
到Left
)。
更奇怪的是,如果我顛倒XAML中的DataTrigger
聲明的順序,那麼它只會在另一個方向(從右到左)動畫。
如果我刪除動畫並在觸發器中將邊距設置爲Setter
,那麼它將按預期工作。另外,如果我將FillBehavior
設置爲Stop
,那麼它會每次向左或向右動畫,但會「捕捉」回默認值。
它看起來好像系統只執行一個Storyboard
,後面在XAML聲明中比當前的「活動」DataTrigger
。
爲什麼會發生這種情況?我該如何解決它?
感謝代碼猴子。正如問題中提到的那樣,我們注意到將填充行爲設置爲「停止」將會「修復」這個問題,但這不是一個真正的解決方案,因爲動畫的全部要點是讓應用看起來很漂亮,並從一個位置跳到另一個(即'FillBehavior =「Stop」')不是一個可行的解決方案。 =(另外,由於缺省的切換行爲是'SnapshotAndReplace',所以現有的故事板不需要被停止,所以一次只能有一個動畫在一個項目上運行。 –