【问题标题】:Slider "animation" in WPF?WPF中的滑块“动画”?
【发布时间】:2012-01-13 12:51:19
【问题描述】:

我有一个按钮和一个滑块,当我按下按钮时,我希望滑块滴答一下,直到达到最大值。

但是,一旦我单击按钮,它会休眠一段时间,然后以最大值显示滑块,而不显示每个刻度。为什么?


这是我的 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 在达到最大值之前不会更新。

如何为滑块创建我想要的“动画”?

【问题讨论】:

    标签: wpf animation user-interface slider


    【解决方案1】:

    您可以将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"));
        }
    }
    

    注意:您需要在项目引用中添加 PresentationFramework.dll 才能在代码中访问 Storyboard 类。

    根据下面的评论更新

    您希望仅使用动画将 Slider.Value 增加整数。由于目标值类型是 Double,因此动画会根据动画帧速率计算 double 值并将其应用于目标。 (默认情况下,动画帧速率为 60 fps,但即使您确实降低了它,它仍然可能会或可能不会根据起始值为您提供偶数值)。我不知道有什么方法可以告诉 DoubleAnimation 只使用偶数值。存在一个 Int32Animation 类,但您不能将其应用于双精度类型的 Slider.Value。

    这是我的 hacky 解决方案(我不太喜欢):将 SliderIntValue (Int32) 依赖属性添加到父级(例如 MainWindow 或您的视图模型)并使用双向绑定将其绑定到 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"));
        }
    }
    

    【讨论】:

    • 谢谢你,这对我帮助很大。
    • 是否可以让这个故事板使用“TickFrequency="1"”设置?现在它的动画也很流畅,看起来不错,但我需要检查它何时点击“1”、“2”而不是“0.1116”等等。
    • 大家好,我想对 Ticks 做同样的事情,但我正在制作没有绑定但背后有代码的动画,我该怎么做?我必须设置什么?我有类似的东西,但我没有工作 --> Storyboard.SetTargetProperty(_DoubleAnimation, new PropertyPath(SliderIntValueProperty));
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-26
    • 1970-01-01
    • 1970-01-01
    • 2012-02-19
    • 2017-03-11
    • 1970-01-01
    相关资源
    最近更新 更多