Слайдер «Анимация» в WPF? - PullRequest
       23

Слайдер «Анимация» в WPF?

3 голосов
/ 13 января 2012

У меня есть кнопка и ползунок, когда я нажимаю кнопку, поэтому я хочу, чтобы ползунок отмечал один шаг, пока не достигнет своего максимального значения. Однако я не заставляю его работать. Как только я нажимаю кнопку, она некоторое время спит, а затем показывает ползунок на максимальном значении, не показывая каждый тик.

Вот мой код 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

Но, как я уже сказал, результат был таким же. Когда я нажимаю кнопку, пользовательский интерфейс не обновляется, пока не достигнет максимального значения.

Итак, мой вопрос: как мне создать эту «анимацию», которую я хочу для слайдера? Направьте меня в правильном направлении, чтобы посмотреть, пожалуйста. :) Спасибо!

1 Ответ

5 голосов
/ 13 января 2012

Вы можете использовать Раскадровка для анимации.

<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 в ссылки на проект, чтобы получить доступ к классу раскадровки в коде.

Обновление за комментарий ниже

Вы хотите увеличить значение Slider.Value на целые числа только с использованием анимации. Поскольку тип целевого значения - Double, анимация рассчитывает и применяет двойные значения к цели на основе частоты кадров анимации. (Частота кадров анимации по умолчанию составляет 60 кадров в секунду, но даже если вы ее уменьшите, это все равно может дать или не дать вам даже значения в зависимости от начального значения). Я не знаю ни одного способа заставить DoubleAnimation использовать только четные значения. Существует класс Int32Animation, но вы не можете применить его к Slider.Value, который имеет тип double.

Вот мое хакерское решение (которое мне не очень нравится): добавьте свойство зависимостей 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"));
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...