ToggleButton动画的启动状态

5
我想为ToggleButton创建一个类似于智能手机上的"Switch"样式的动画。
动画本身不是问题,开关看起来很漂亮,并且在我点击它时进行了动画处理。但当它被加载并打开时,它也会进行动画处理。
当我加载视图时,它应该显示一些开关处于打开状态,一些开关处于关闭状态。但它只显示“关闭”,并自动开始“打开”动画。
以下简单的代码展示了我的问题:当选中时,按钮的宽度变为150像素。
<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        x:Class="AnimationTest2.MainWindow"
        Title="MainWindow" Height="350" Width="525">

    <Window.Resources>
        <Style TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource {x:Type ToggleButton}}" x:Key="SwitchStyle">
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsChecked, RelativeSource={RelativeSource Self}}" Value="true">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard Storyboard.TargetProperty="Width">
                                <DoubleAnimation To="150"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                    <DataTrigger.ExitActions>
                        <BeginStoryboard>
                            <Storyboard Storyboard.TargetProperty="Width">
                                <DoubleAnimation To="50"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.ExitActions>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>

    <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
        <ToggleButton Width="50" Content="Button" Style="{StaticResource ResourceKey=SwitchStyle}"/>
        <ToggleButton Width="50" Content="Button" Style="{StaticResource ResourceKey=SwitchStyle}" IsChecked="True"/>
    </StackPanel>
</Window>

第一个ToggleButton正常工作。单击时,它未被选中并动画到150px。
第二个ToggleButton默认已选中且应立即为150px,但实际上它会在我启动应用程序时开始增长!
一些方法可以根据IsChecked状态定义ToggleButton的初始状态,并仅在单击时开始动画。我该如何实现呢?
我也尝试过使用VisualStateManager,就像此答案中所述,但是我遇到了同样的问题...
更新
这是实际工作中的开关,如果有人不仅仅对概念证明感兴趣:
    <Style TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource {x:Type ToggleButton}}" x:Key="SwitchToggleButton">
        <Setter Property="BorderBrush" Value="Black"/>
        <Setter Property="Background" Value="Gray"/>
        <Setter Property="Foreground" Value="Black"/>
        <Setter Property="Width" Value="70"/>
        <Setter Property="Height" Value="30"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ToggleButton}">
                    <Grid>
                        <Border x:Name="BackBorder" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}"/>
                        <TextBlock x:Name="Off" Margin="30,0,0,0" VerticalAlignment="Center"  HorizontalAlignment="Center"><Run Text="OFF"/></TextBlock>
                        <TextBlock x:Name="On" Margin="0,0,30,0" VerticalAlignment="Center"  HorizontalAlignment="Center"><Run Text="ON"/></TextBlock>
                        <Border x:Name="Slider" Background="LightGray" Width="30" Height="30" HorizontalAlignment="Left" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <EventTrigger RoutedEvent="Border.Loaded" SourceName="Slider">
                            <SkipStoryboardToFill BeginStoryboardName="checkedSB" />
                            <SkipStoryboardToFill BeginStoryboardName="checkedSB2" />
                            <SkipStoryboardToFill BeginStoryboardName="uncheckedSB" />
                            <SkipStoryboardToFill BeginStoryboardName="uncheckedSB2" />
                        </EventTrigger>
                        <DataTrigger Binding="{Binding IsChecked, RelativeSource={RelativeSource Self}}" Value="true">
                            <DataTrigger.EnterActions>
                                <BeginStoryboard x:Name="checkedSB">
                                    <Storyboard Storyboard.TargetProperty="Margin" Storyboard.TargetName="Slider">
                                        <ThicknessAnimation To="40,0,0,0" Duration="00:00:00.2"/>
                                    </Storyboard>
                                </BeginStoryboard>
                                <BeginStoryboard x:Name="checkedSB2">
                                    <Storyboard Storyboard.TargetProperty="(Control.Background).(SolidColorBrush.Color)">
                                        <ColorAnimation To="LightSeaGreen" Duration="00:00:00.3"/>
                                    </Storyboard>
                                </BeginStoryboard>
                            </DataTrigger.EnterActions>
                            <DataTrigger.ExitActions>
                                <BeginStoryboard x:Name="uncheckedSB">
                                    <Storyboard Storyboard.TargetProperty="Margin" Storyboard.TargetName="Slider">
                                        <ThicknessAnimation To="0" Duration="00:00:00.2"/>
                                    </Storyboard>
                                </BeginStoryboard>
                                <BeginStoryboard x:Name="uncheckedSB2">
                                    <Storyboard Storyboard.TargetProperty="(Control.Background).(SolidColorBrush.Color)">
                                        <ColorAnimation To="{x:Null}" Duration="00:00:00.3"/>
                                    </Storyboard>
                                </BeginStoryboard>
                            </DataTrigger.ExitActions>
                        </DataTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
1个回答

6
您可以将 SkipStoryboardToFill 对象添加到 Loaded EventTrigger 中。代码应如下所示。
<Style.Triggers>
    <EventTrigger RoutedEvent="ToggleButton.Loaded">
        <SkipStoryboardToFill BeginStoryboardName="checkedSB" />
        <SkipStoryboardToFill BeginStoryboardName="uncheckedSB" />
    </EventTrigger>
    <DataTrigger Binding="{Binding IsChecked, RelativeSource={RelativeSource Self}}" Value="true">
        <DataTrigger.EnterActions>
            <BeginStoryboard Name="checkedSB">
                <Storyboard Storyboard.TargetProperty="Width">
                    <DoubleAnimation To="150"/>
                </Storyboard>
            </BeginStoryboard>
        </DataTrigger.EnterActions>
        <DataTrigger.ExitActions>
            <BeginStoryboard Name="uncheckedSB">
                <Storyboard Storyboard.TargetProperty="Width">
                    <DoubleAnimation To="50"/>
                </Storyboard>
            </BeginStoryboard>
        </DataTrigger.ExitActions>
    </DataTrigger>
</Style.Triggers>

运行得非常好 - 而且非常容易!我想知道为什么这不是来自 MS 的 ToggleButton 样式示例的一部分,因为我看到的所有使用动画的样式都有这个问题。 - JCH2k
实际上,我在Visual Studio 2010帮助页面的“故事板概述”中找到了它 =) 但是我花费的时间比预期的要长。 - bars222
在我的真实应用程序中,我不得不将EventTrigger绑定到其他东西,例如<EventTrigger RoutedEvent="Border.Loaded" SourceName="Border">并将其中一个边框命名为“Border”,以使其与延迟加载正确配合使用。否则,我会再次遇到初始效果...我将发布我的可工作代码如上所述... - JCH2k
谢谢,很有趣。 - bars222

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接