WPF中的滑块“动画”?

3

我有一个按钮和一个滑块,当我按下按钮时,我希望滑块向前走一步,直到它达到最大值。

但是,一旦我点击按钮,它会暂停一段时间,然后显示滑块处于最大值,而没有显示每个步骤。这是为什么?


这是我的XAML代码:

<StackPanel Orientation="Horizontal">
    <Button x:Name="AnimationGoButton" Content="Go" />
    <Slider x:Name="AnimationSlider" TickFrequency="1" TickPlacement="BottomRight" IsSnapToTickEnabled="True" Width="200" Maximum="20" Value="0" />
</StackPanel>

以下是我的后端代码:

Private Sub AnimationGoButton_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles AnimationGoButton.Click
    While (Me.AnimationSlider.Value < Me.AnimationSlider.Maximum)
        Me.AnimationSlider.Value += 1
        System.Threading.Thread.Sleep(100)
    End While
End Sub

我尝试使用动态资源,但结果仍然相同。

XAML:

<Window.Resources>
    <sys:Double x:Key="AnimationSliderValue">0</sys:Double>
</Window.Resources>

然后我在XAML中更改了滑块的值:

Value="{DynamicResource AnimationSliderValue}"

并将代码更改为:

While (Me.AnimationSlider.Value < Me.AnimationSlider.Maximum)
    Resources("AnimationSliderValue") += 1
    System.Threading.Thread.Sleep(100)
End While

结果是一样的。当我按下按钮时,UI不会更新,直到它达到最大值。
我该如何为滑块创建所需的“动画”?
1个回答

5
你可以使用 Storyboard 来制作动画。
<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525" x:Name="userControl">
<Window.Resources>
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
    <Storyboard x:Key="SlideUpAnimation">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(RangeBase.Value)" Storyboard.TargetName="slider1">
            <EasingDoubleKeyFrame KeyTime="0:0:1" Value="10"/>
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>
    <Storyboard x:Key="SlideDownAnimation">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(RangeBase.Value)" Storyboard.TargetName="slider1">
            <SplineDoubleKeyFrame KeyTime="0:0:1" Value="0"/>
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>
</Window.Resources>
<Window.Triggers>
    <EventTrigger RoutedEvent="FrameworkElement.Loaded">
        <BeginStoryboard Storyboard="{StaticResource SlideUpAnimation}"/>
    </EventTrigger>
</Window.Triggers>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Top">
    <Button x:Name="btnSlideDown" Click="btnSlideDown_Click" Content="Slide Down" HorizontalAlignment="Center" VerticalAlignment="Center"/>
    <Slider Height="23" x:Name="slider1" Width="100" />
    <Button x:Name="btnSlideUp" Click="btnSlideUp_Click" HorizontalAlignment="Center" VerticalAlignment="Center" Content="Slide Up" />
</StackPanel>

然后在按钮点击时启动故事板:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void btnSlideUp_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        this.BeginStoryboard((Storyboard)this.FindResource("SlideUpAnimation"));
    }

    private void btnSlideDown_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        this.BeginStoryboard((Storyboard)this.FindResource("SlideDownAnimation"));
    }
}

注意:在代码中访问Storyboard类,需要将PresentationFramework.dll添加到项目引用中。
根据下面的评论更新:
您想使用动画仅按整数递增Slider.Value。由于目标值类型为Double,动画会根据动画帧率计算和应用Double值到目标上(默认情况下,动画帧率为60 fps,但即使您降低它,根据起始值,仍可能无法得到偶数值)。我不知道有什么方法可以告诉DoubleAnimation仅使用偶数值。存在一个Int32Animation类,但您无法将其应用于类型为double的Slider.Value。
这是我的hacky解决方案(我不太喜欢):向父级(例如MainWindow或您的ViewModel)添加一个SliderIntValue(Int32)依赖属性,并使用双向绑定将其绑定到Slider.Value。 Binding类会自动处理类型转换。然后将动画应用于SliderIntValue而不是滑块本身:
<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525" x:Name="userControl">
<Window.Resources>
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
    <Storyboard x:Key="SlideUpAnimation">
        <Int32AnimationUsingKeyFrames Storyboard.TargetProperty="SliderIntValue" Storyboard.TargetName="userControl">
            <EasingInt32KeyFrame KeyTime="0:0:1" Value="10"/>
        </Int32AnimationUsingKeyFrames>
    </Storyboard>
    <Storyboard x:Key="SlideDownAnimation">
        <Int32AnimationUsingKeyFrames Storyboard.TargetProperty="SliderIntValue" Storyboard.TargetName="userControl">
            <EasingInt32KeyFrame KeyTime="0:0:1" Value="0"/>
        </Int32AnimationUsingKeyFrames>
    </Storyboard>
</Window.Resources>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Top">
    <Button x:Name="btnSlideDown" Click="btnSlideDown_Click" Content="Slide Down" HorizontalAlignment="Center" VerticalAlignment="Center"/>
    <Slider Height="23" x:Name="slider1" Width="100" IsSnapToTickEnabled="True" Value="{Binding SliderIntValue, ElementName=userControl, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
    <Button x:Name="btnSlideUp" Click="btnSlideUp_Click" HorizontalAlignment="Center" VerticalAlignment="Center" Content="Slide Up" />
    <TextBox TextWrapping="Wrap" Text="{Binding Value, ElementName=slider1}" Margin="20,0,0,0"/>
</StackPanel>

这里是添加到MainWindow类中的依赖属性:
public partial class MainWindow : Window
{
    public static readonly DependencyProperty SliderIntValueProperty = DependencyProperty.Register("SliderIntValue",
                typeof(int), typeof(MainWindow));

    public MainWindow()
    {
        InitializeComponent();
    }

    private void btnSlideUp_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        this.BeginStoryboard((Storyboard)this.FindResource("SlideUpAnimation"));
    }

    private void btnSlideDown_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        this.BeginStoryboard((Storyboard)this.FindResource("SlideDownAnimation"));
    }
}

这个Storyboard能否使用“TickFrequency =“1””设置?目前它动画平滑,看起来很不错,但我需要检查它何时达到“1”,“2”而不是“0.1116”等。 - Ragowit
大家好,我想用Ticks做同样的事情,但是我是在代码后端而不是绑定中进行动画处理的,我该怎么做?我需要设置什么?我有类似于这样的东西,但它不起作用--> Storyboard.SetTargetProperty(_DoubleAnimation, new PropertyPath(SliderIntValueProperty)); - vkampouris

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