为什么之前选择的 tabitem 和选择的 tabitem 的动画开始工作正常,然后就不能正常工作了?

why the animation of previous selected tabitem and selected tabitem started working fine, then it didn't work fine?

之前选择的tabitem和选择的tabitem的动画开始工作正常,然后就不能正常工作了。

在我看来,代码应该可以正常工作。不知道为什么现在动画不正确

MainWindow.xaml:

<Window.Resources>
        <local:TestViewModel x:Key="vm"/>
        <Style TargetType="{x:Type Rectangle}">
            <Setter Property="Visibility" Value="Visible"/>
            <Setter Property="IsEnabled" Value="True"/>
            <Style.Triggers>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding  PreviousSelected }" Value="0"/>
                        <Condition Binding="{Binding ElementName=TestTabs, Path=SelectedIndex}" Value="1"/>
                    </MultiDataTrigger.Conditions>
                    <MultiDataTrigger.EnterActions>
                        <BeginStoryboard Name="MyBeginStoryboard1">
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="0" To="40" Duration="0:0:0.2"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </MultiDataTrigger.EnterActions>
                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding  PreviousSelected }" Value="0"/>
                        <Condition Binding="{Binding ElementName=TestTabs, Path=SelectedIndex}" Value="2"/>
                    </MultiDataTrigger.Conditions>
                    <MultiDataTrigger.EnterActions>
                        <BeginStoryboard Name="MyBeginStoryboard3">
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="0" To="75" Duration="0:0:0.2"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </MultiDataTrigger.EnterActions>
                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding  PreviousSelected }" Value="0"/>
                        <Condition Binding="{Binding ElementName=TestTabs, Path=SelectedIndex}" Value="3"/>
                    </MultiDataTrigger.Conditions>
                    <MultiDataTrigger.EnterActions>
                        <BeginStoryboard Name="MyBeginStoryboard5">
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="0" To="115" Duration="0:0:0.2"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </MultiDataTrigger.EnterActions>
                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding  PreviousSelected }" Value="1"/>
                        <Condition Binding="{Binding ElementName=TestTabs, Path=SelectedIndex}" Value="0"/>
                    </MultiDataTrigger.Conditions>
                    <MultiDataTrigger.EnterActions>
                        <BeginStoryboard Name="MyBeginStoryboard11">
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="40" To="0" Duration="0:0:0.2"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </MultiDataTrigger.EnterActions>
                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding  PreviousSelected }" Value="1"/>
                        <Condition Binding="{Binding ElementName=TestTabs, Path=SelectedIndex}" Value="2"/>
                    </MultiDataTrigger.Conditions>
                    <MultiDataTrigger.EnterActions>
                        <BeginStoryboard Name="MyBeginStoryboard7">
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="40" To="75" Duration="0:0:0.2"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </MultiDataTrigger.EnterActions>
                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding  PreviousSelected }" Value="1"/>
                        <Condition Binding="{Binding ElementName=TestTabs, Path=SelectedIndex}" Value="3"/>
                    </MultiDataTrigger.Conditions>
                    <MultiDataTrigger.EnterActions>
                        <BeginStoryboard Name="MyBeginStoryboard9">
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="40" To="115" Duration="0:0:0.2"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </MultiDataTrigger.EnterActions>
                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding  PreviousSelected }" Value="2"/>
                        <Condition Binding="{Binding ElementName=TestTabs, Path=SelectedIndex}" Value="0"/>

                    </MultiDataTrigger.Conditions>
                    <MultiDataTrigger.EnterActions>
                        <BeginStoryboard Name="MyBeginStoryboard13">
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="70" To="0" Duration="0:0:0.2"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </MultiDataTrigger.EnterActions>
                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding  PreviousSelected }" Value="2"/>
                        <Condition Binding="{Binding ElementName=TestTabs, Path=SelectedIndex}" Value="1"/>
                    </MultiDataTrigger.Conditions>
                    <MultiDataTrigger.EnterActions>
                        <BeginStoryboard Name="MyBeginStoryboard15">
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="70" To="40" Duration="0:0:0.2"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </MultiDataTrigger.EnterActions>
                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding  PreviousSelected }" Value="2"/>
                        <Condition Binding="{Binding ElementName=TestTabs, Path=SelectedIndex}" Value="3"/>
                    </MultiDataTrigger.Conditions>
                    <MultiDataTrigger.EnterActions>
                        <BeginStoryboard Name="MyBeginStoryboard17">
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="70" To="115" Duration="0:0:0.2"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </MultiDataTrigger.EnterActions>
                </MultiDataTrigger>
               
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid  DataContext="{StaticResource vm}" >
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="50"/>
        </Grid.RowDefinitions>
        <TabControl     SelectedIndex="{Binding Selected,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"     Grid.Row="0"   x:Name="TestTabs">
            <TabItem Name="Tab1" Header="News" />
            <TabItem Name="Tab2" Header="DLC" />
            <TabItem Name="Tab3" Header="Settings"/>
        </TabControl>
        <DockPanel  x:Name="rp" Grid.Row="0" LastChildFill="False" HorizontalAlignment="Stretch">
            <Canvas DockPanel.Dock="Left" >
                <Rectangle x:Name="Rect1" Fill="#ff0000" VerticalAlignment="Top"  Height="4" Margin="0,25,0,0" 
                           SnapsToDevicePixels="True" UseLayoutRounding="True" RenderOptions.EdgeMode="Aliased" 
                           Width="{Binding ElementName=TestTabs, Path=SelectedItem.ActualWidth}"  RenderOptions.BitmapScalingMode="HighQuality" />
            </Canvas>
        </DockPanel>
        <StackPanel Orientation="Horizontal" Grid.Row="1">
            <Label Content="selected" Width="100" Height="40" />
            <TextBox x:Name="sele" Text="{Binding Selected}" Width="100" Height="40" Background="AliceBlue" Margin="5"/>
            <Label Content="previousSelected"  Width="100" Height="40"/>
            <TextBox x:Name="prev" Text="{Binding PreviousSelected,Mode=OneWay}" Width="100" Height="40" Background="AliceBlue" Margin="5"/>
        </StackPanel>
    </Grid>

MainWindow.xaml.cs:

using System.ComponentModel;
using System.Windows;
namespace TabControlBindSlide
{
  public partial class MainWindow : Window
  {
    public MainWindow()
    {
      InitializeComponent();
    }
  }
  class TestViewModel : INotifyPropertyChanged
  {
    private int _selected;
    public int Selected
    {
      get { return _selected; }
      set
      {
        int temp = _selected;
        _selected = value;
        _previousSelected = temp;
        NotifyPropertyChanged("Selected", temp, value);
        NotifyPropertyChanged("PreviousSelected", temp, temp);
      }
    }
    int _previousSelected = 0;
    public int PreviousSelected
    {
      get { return _previousSelected; }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    protected void NotifyPropertyChanged<T>(string propertyName, T oldvalue, T newvalue)
    {
      OnPropertyChanged(this, new PropertyChangedExtendedEventArgs<T>(propertyName, oldvalue, newvalue));
    }
    public virtual void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
      PropertyChangedEventHandler handler = PropertyChanged;
      if (handler != null)
        handler(sender, e);
    }
  }
  public class PropertyChangedExtendedEventArgs<T> : PropertyChangedEventArgs
  {
    public virtual T OldValue { get; private set; }
    public virtual T NewValue { get; private set; }

    public PropertyChangedExtendedEventArgs(string propertyName, T oldValue, T newValue)
        : base(propertyName)
    {
      OldValue = oldValue;
      NewValue = newValue;
    }
  }

}

结果: 动画开始工作正常,然后就不行了。

问题;您不应该删除您创建的 Storyboard,您应该在完成 Storyboard 后删除它。因为一个已经存在的Storyboard不会重建,它只会在第一次时成功。如果您按如下方式渲染所有 Storyboards,它将正常工作。

    <Window.Resources>
    <local:TestViewModel x:Key="vm"/>
    <Style TargetType="{x:Type Rectangle}">
        <Setter Property="Visibility" Value="Visible"/>
        <Setter Property="IsEnabled" Value="True"/>
        <Style.Triggers>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding  PreviousSelected }" Value="0"/>
                    <Condition Binding="{Binding ElementName=TestTabs, Path=SelectedIndex}" Value="1"/>
                </MultiDataTrigger.Conditions>
                <MultiDataTrigger.EnterActions>
                    <BeginStoryboard Name="MyBeginStoryboard1">
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="0" To="40" Duration="0:0:0.2"></DoubleAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </MultiDataTrigger.EnterActions>
                <MultiDataTrigger.ExitActions>
                    <RemoveStoryboard BeginStoryboardName="MyBeginStoryboard1" />
                </MultiDataTrigger.ExitActions>
            </MultiDataTrigger>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding  PreviousSelected }" Value="0"/>
                    <Condition Binding="{Binding ElementName=TestTabs, Path=SelectedIndex}" Value="2"/>
                </MultiDataTrigger.Conditions>
                <MultiDataTrigger.EnterActions>
                    <BeginStoryboard Name="MyBeginStoryboard3">
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="0" To="75" Duration="0:0:0.2"></DoubleAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </MultiDataTrigger.EnterActions>
                <MultiDataTrigger.ExitActions>
                    <RemoveStoryboard BeginStoryboardName="MyBeginStoryboard3" />
                </MultiDataTrigger.ExitActions>
            </MultiDataTrigger>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding  PreviousSelected }" Value="0"/>
                    <Condition Binding="{Binding ElementName=TestTabs, Path=SelectedIndex}" Value="3"/>
                </MultiDataTrigger.Conditions>
                <MultiDataTrigger.EnterActions>
                    <BeginStoryboard Name="MyBeginStoryboard5">
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="0" To="115" Duration="0:0:0.2"></DoubleAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </MultiDataTrigger.EnterActions>
                <MultiDataTrigger.ExitActions>
                    <RemoveStoryboard BeginStoryboardName="MyBeginStoryboard5" />
                </MultiDataTrigger.ExitActions>
            </MultiDataTrigger>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding  PreviousSelected }" Value="1"/>
                    <Condition Binding="{Binding ElementName=TestTabs, Path=SelectedIndex}" Value="0"/>
                </MultiDataTrigger.Conditions>
                <MultiDataTrigger.EnterActions>
                    <BeginStoryboard Name="MyBeginStoryboard11">
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="40" To="0" Duration="0:0:0.2"></DoubleAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </MultiDataTrigger.EnterActions>
                <MultiDataTrigger.ExitActions>
                    <RemoveStoryboard BeginStoryboardName="MyBeginStoryboard11" />
                </MultiDataTrigger.ExitActions>
            </MultiDataTrigger>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding  PreviousSelected }" Value="1"/>
                    <Condition Binding="{Binding ElementName=TestTabs, Path=SelectedIndex}" Value="2"/>
                </MultiDataTrigger.Conditions>
                <MultiDataTrigger.EnterActions>
                    <BeginStoryboard Name="MyBeginStoryboard7">
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="40" To="75" Duration="0:0:0.2"></DoubleAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </MultiDataTrigger.EnterActions>
                <MultiDataTrigger.ExitActions>
                    <RemoveStoryboard BeginStoryboardName="MyBeginStoryboard7" />
                </MultiDataTrigger.ExitActions>
            </MultiDataTrigger>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding  PreviousSelected }" Value="1"/>
                    <Condition Binding="{Binding ElementName=TestTabs, Path=SelectedIndex}" Value="3"/>
                </MultiDataTrigger.Conditions>
                <MultiDataTrigger.EnterActions>
                    <BeginStoryboard Name="MyBeginStoryboard9">
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="40" To="115" Duration="0:0:0.2"></DoubleAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </MultiDataTrigger.EnterActions>
                <MultiDataTrigger.ExitActions>
                    <RemoveStoryboard BeginStoryboardName="MyBeginStoryboard9" />
                </MultiDataTrigger.ExitActions>
            </MultiDataTrigger>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding  PreviousSelected }" Value="2"/>
                    <Condition Binding="{Binding ElementName=TestTabs, Path=SelectedIndex}" Value="0"/>

                </MultiDataTrigger.Conditions>
                <MultiDataTrigger.EnterActions>
                    <BeginStoryboard Name="MyBeginStoryboard13">
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="70" To="0" Duration="0:0:0.2"></DoubleAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </MultiDataTrigger.EnterActions>
                <MultiDataTrigger.ExitActions>
                    <RemoveStoryboard BeginStoryboardName="MyBeginStoryboard13" />
                </MultiDataTrigger.ExitActions>
            </MultiDataTrigger>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding  PreviousSelected }" Value="2"/>
                    <Condition Binding="{Binding ElementName=TestTabs, Path=SelectedIndex}" Value="1"/>
                </MultiDataTrigger.Conditions>
                <MultiDataTrigger.EnterActions>
                    <BeginStoryboard Name="MyBeginStoryboard15">
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="70" To="40" Duration="0:0:0.2"></DoubleAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </MultiDataTrigger.EnterActions>
                <MultiDataTrigger.ExitActions>
                    <RemoveStoryboard BeginStoryboardName="MyBeginStoryboard15" />
                </MultiDataTrigger.ExitActions>
            </MultiDataTrigger>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding  PreviousSelected }" Value="2"/>
                    <Condition Binding="{Binding ElementName=TestTabs, Path=SelectedIndex}" Value="3"/>
                </MultiDataTrigger.Conditions>
                <MultiDataTrigger.EnterActions>
                    <BeginStoryboard Name="MyBeginStoryboard17">
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="70" To="115" Duration="0:0:0.2"></DoubleAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </MultiDataTrigger.EnterActions>
            </MultiDataTrigger>

        </Style.Triggers>
    </Style>
</Window.Resources>
<Grid  DataContext="{StaticResource vm}" >
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="50"/>
    </Grid.RowDefinitions>
    <TabControl     SelectedIndex="{Binding Selected,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"     Grid.Row="0"   x:Name="TestTabs">
        <TabItem Name="Tab1" Header="News" />
        <TabItem Name="Tab2" Header="DLC" />
        <TabItem Name="Tab3" Header="Settings"/>
    </TabControl>
    <DockPanel  x:Name="rp" Grid.Row="0" LastChildFill="False" HorizontalAlignment="Stretch">
        <Canvas DockPanel.Dock="Left" >
            <Rectangle x:Name="Rect1" Fill="#ff0000" VerticalAlignment="Top"  Height="4" Margin="0,25,0,0" 
                       SnapsToDevicePixels="True" UseLayoutRounding="True" RenderOptions.EdgeMode="Aliased" 
                       Width="{Binding ElementName=TestTabs, Path=SelectedItem.ActualWidth}"  RenderOptions.BitmapScalingMode="HighQuality" />
        </Canvas>
    </DockPanel>
    <StackPanel Orientation="Horizontal" Grid.Row="1">
        <Label Content="selected" Width="100" Height="40" />
        <TextBox x:Name="sele" Text="{Binding Selected}" Width="100" Height="40" Background="AliceBlue" Margin="5"/>
        <Label Content="previousSelected"  Width="100" Height="40"/>
        <TextBox x:Name="prev" Text="{Binding PreviousSelected,Mode=OneWay}" Width="100" Height="40" Background="AliceBlue" Margin="5"/>
    </StackPanel>
</Grid>