c# - WPF 模板中的平滑动画 ProgressBar

标签 c# wpf mvvm progress-bar

我正在开发一个 MVVM 应用程序,我希望有一个 ProgressBar,当该属性发生变化时,它可以平滑地为它的新值设置动画。我已经使用 c# 看到了这个问题的几个答案,但我更愿意在模板中完成所有这些。我遇到的问题是正确设置和定位事件和 Storyboard。这是我目前拥有的:

进度条-

样式-(只是触发器)

                    <ControlTemplate.Triggers>
                    <EventTrigger RoutedEvent="RangeBase.ValueChanged">
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation
                                    Storyboard.TargetName="???????" 
                                    Storyboard.TargetProperty="Value"
                                    To="???????" Duration="0:0:5"  />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>

我从这里获取了触发代码:http://msdn.microsoft.com/en-us/library/system.windows.controls.progressbar(v=vs.110).aspx .

如何将 TargetName 设置为模板本身,以便它应用于使用该模板的所有控件?如何将“To”设置为传入值?似乎有一种方法可以获取“绑定(bind)”值,但我将 Value 和 Max 都绑定(bind)到进度条元素上。它怎么知道要使用什么?

这里是整个模板供引用:

    <Style x:Key="ProgressStyle" TargetType="{x:Type ProgressBar}">
    <Setter Property="OverridesDefaultStyle" Value="True" />
    <Setter Property="SnapsToDevicePixels" Value="True" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ProgressBar}">
                <Grid MinHeight="14" MinWidth="20">
                    <Border x:Name="BaseRectangle" Background="{StaticResource BaseColor}" CornerRadius="10,0,10,0"></Border>
                    <Border x:Name="GlassRectangle" CornerRadius="10,0,10,0"  Background="{StaticResource GlassFX}" Panel.ZIndex="10"></Border>
                    <Border x:Name="animation" CornerRadius="10,0,10,0" Opacity=".7" Background="{Binding Path=Foreground, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Left"></Border>
                    <Border x:Name="PART_Indicator" CornerRadius="10,0,10,0" Background="{Binding Path=Foreground, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Left"></Border>
                    <Border x:Name="PART_Track" BorderThickness="1" CornerRadius="10,0,10,0" BorderBrush="Black"></Border>
                    <Border x:Name="BordeCabeceraSombra" BorderThickness="2" CornerRadius="10,0,10,0" BorderBrush="DarkGray" Opacity=".2" Margin="1,1,1,0"></Border>
                    <Label x:Name="Progress" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontWeight="Bold" Foreground="White" Opacity=".7" Content="{Binding Path=Value, RelativeSource={RelativeSource TemplatedParent}}"></Label>
                </Grid>
                <ControlTemplate.Triggers>
                    <EventTrigger RoutedEvent="RangeBase.ValueChanged">
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation
                                    Storyboard.TargetName="???????" 
                                    Storyboard.TargetProperty="Value"
                                    From="???????" To="???????" Duration="0:0:5"  />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                    <Trigger Property="IsIndeterminate" Value="True">
                        <Setter Property="Visibility" TargetName="Progress" Value="Hidden"></Setter>
                        <Setter Property="Background" TargetName="PART_Indicator">
                            <Setter.Value>
                                <MultiBinding>
                                    <MultiBinding.Converter>
                                        <wintheme:ProgressBarHighlightConverter/>
                                    </MultiBinding.Converter>
                                    <Binding Source="{StaticResource GlowFXProgressAnimated}"/>
                                    <Binding Path="ActualWidth"  ElementName="BaseRectangle"/>
                                    <Binding Path="ActualHeight" ElementName="BaseRectangle"/>
                                </MultiBinding>
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter Property="Opacity" Value=".5"></Setter>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

如有任何帮助,我们将不胜感激!

最佳答案

我认为这是更好的方法。

您可以创建行为来执行此操作。 (MVVM WPF)

创建类:

class ProgresBarAnimateBehavior : Behavior<ProgressBar>
{
    bool _IsAnimating = false;

    protected override void OnAttached()
    {
        base.OnAttached();
        ProgressBar progressBar = this.AssociatedObject;
        progressBar.ValueChanged += ProgressBar_ValueChanged;
    }

    private void ProgressBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
    {
        if (_IsAnimating)
            return;

        _IsAnimating = true;

        DoubleAnimation doubleAnimation = new DoubleAnimation
            (e.OldValue, e.NewValue, new Duration(TimeSpan.FromSeconds(0.3)), FillBehavior.Stop);
        doubleAnimation.Completed += Db_Completed;

        ((ProgressBar)sender).BeginAnimation(ProgressBar.ValueProperty, doubleAnimation);

        e.Handled = true;
    }

    private void Db_Completed(object sender, EventArgs e)
    {
        _IsAnimating = false;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        ProgressBar progressBar = this.AssociatedObject;
        progressBar.ValueChanged -= ProgressBar_ValueChanged;
    }
}

简单的用法:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:b="clr-namespace:YOURNAMESPACE.Behaviors"

<ProgressBar Height="7"
             Value="{Binding LoadingValue}">

    <i:Interaction.Behaviors>
        <b:ProgresBarAnimateBehavior />
    </i:Interaction.Behaviors>
</ProgressBar>

关于c# - WPF 模板中的平滑动画 ProgressBar,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26618308/

相关文章:

c# - WPF MVVM - 单元测试命令 - 私有(private)方法与公共(public)方法?

mvvm - 清理 ViewModels MVVM Light 和 Xamarin 表单

c# - 在异步方法中捕获异常后激活

c# - 使用 NInject 为通用接口(interface)注册通用类

通过泛型实现的 C# 参数化属性类?

wpf - DockPanel 子元素的顺序背后的逻辑是什么

c# - 无法分配 datagridview.columns[i].Width 属性

sql-server - 从 Visual Studio 2010 创建 .MDF 文件时出现问题

WPF 不在远程桌面上呈现

c# - 转换器无法将类型 'system.datetime' 的值转换为 Windows Phone 8.1 Datepicker 中的类型 'datetime'