带有对角线装饰的进度条主题

11

我想要将WPF ProgressBar装饰成下面这张图片的样子:

当前状态:

无装饰的ProgressBar

装饰后:

有装饰的ProgressBar

此外,那些空白对角线应该从左到右以跑马灯动画移动。目前我只有这个简单的样式来呈现当前的外观:

<Style x:Key="{x:Type ProgressBar}" TargetType="{x:Type ProgressBar}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ProgressBar}">
                <Border x:Name="BorderBackground" CornerRadius="3" BorderThickness="1" BorderBrush="{StaticResource ProgressBarBorderBrush}" Background="{StaticResource ProgressBarBackgroundBrush}">
                    <Grid>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Determinate" />
                                <VisualState x:Name="Indeterminate" />
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <Border x:Name="PART_Track" Margin="2" BorderThickness="1" CornerRadius="2" />
                        <Border x:Name="PART_Indicator" Margin="2" BorderThickness="1" CornerRadius="2" HorizontalAlignment="Left" Background="{StaticResource ProgressBarTrackBackgroundBrush}"/>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

有人可以帮我获取它吗?我搜索了一下,但可能错过了正确的关键字以查找类似这样的内容,至少我通常会看到(例如在OS X进度条上)通常使用这种“装饰”。

提前感谢;).


具有答案代码的解决方案模板稍作修改:

<Style x:Key="{x:Type ProgressBar}" TargetType="{x:Type ProgressBar}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ProgressBar}">
                <Border x:Name="BorderBackground" CornerRadius="3" BorderThickness="1" BorderBrush="{StaticResource ProgressBarBorderBrush}" Background="{StaticResource ProgressBarBackgroundBrush}" Effect="{StaticResource LightStrongDownLinearShadowEffect}">
                    <Grid>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Determinate" />
                                <VisualState x:Name="Indeterminate" />
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <Border x:Name="PART_Track" Margin="2" BorderThickness="1" CornerRadius="2" />
                        <Border x:Name="PART_Indicator" Margin="2" BorderThickness="1" CornerRadius="2" HorizontalAlignment="Left" Background="{StaticResource ProgressBarTrackBackgroundBrush}" ClipToBounds="True">
                            <Border x:Name="DiagonalDecorator" Width="5000">
                                <Border.Background>
                                    <DrawingBrush TileMode="Tile" Stretch="None" Viewbox="0,0,1,1" Viewport="0,0,25,25" ViewportUnits="Absolute">
                                        <DrawingBrush.RelativeTransform>
                                            <TranslateTransform X="0" Y="0" />
                                        </DrawingBrush.RelativeTransform>
                                        <DrawingBrush.Drawing>
                                            <GeometryDrawing Brush="#20FFFFFF" Geometry="M10,0 22,0 12,25 0,22 Z" />
                                        </DrawingBrush.Drawing>
                                    </DrawingBrush>
                                </Border.Background>
                                <Border.Triggers>
                                    <EventTrigger RoutedEvent="FrameworkElement.Loaded">
                                        <BeginStoryboard>
                                            <Storyboard>
                                                <DoubleAnimation Storyboard.TargetProperty="(Border.Background).(DrawingBrush.RelativeTransform).(TranslateTransform.X)" From="0" To=".25" RepeatBehavior="Forever" Duration="0:0:15" />
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </EventTrigger>
                                </Border.Triggers>
                            </Border>
                        </Border>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

1
请注意,带有动画和渐变的进度条可能会适得其反;当您已经在等待某些操作时,它会消耗CPU时间... - Emond
嗯,我在测试时没有看到任何性能问题。如果我发现了什么,我会发布的。谢谢建议;) - dbalboa
Windows Phone的进度条因为消耗过多的电量而出了名:http://www.jeff.wilcox.name/2010/08/performanceprogressbar/ - Emond
如果您这么长时间后仍然拥有它们,您介意发布这些画笔吗? - Delusional Logic
3个回答

4

编辑:

这篇来自codeproject.com的文章有一个“barber pole”进度条的工作版本。在文章中搜索“CandyCaneProgressPainter”。

之前的回答:

这篇几乎完全符合您的要求。您只需要将矩形的可见性限制在所需百分比,并更改高度/宽度比即可。

您需要的关键字是“storyboard”,“animate”和“trigger”

以下是链接中的xaml,并带有一些使动画平滑的注释:

 <Rectangle x:Name="pole" Width="100" Height="20" Stroke="Black" StrokeThickness="1">
  <Rectangle.Fill>
   <DrawingBrush TileMode="Tile" Stretch="None" Viewbox="0,0,1,1" Viewport="0,0,25,25" ViewportUnits="Absolute">
    <DrawingBrush.RelativeTransform>
     <TranslateTransform X="0" Y="0" />
    </DrawingBrush.RelativeTransform>
    <DrawingBrush.Drawing>
     <GeometryDrawing Brush="Red" Geometry="M10,0 25,0 15,25 0,25 Z" />    </DrawingBrush.Drawing>
   </DrawingBrush>
  </Rectangle.Fill>
  <Rectangle.Triggers>
   <EventTrigger RoutedEvent="FrameworkElement.Loaded">
    <BeginStoryboard>
     <Storyboard>
      <DoubleAnimation Storyboard.TargetProperty="(Rectangle.Fill).(DrawingBrush.RelativeTransform).(TranslateTransform.X)" From="0" To=".25" RepeatBehavior="Forever" Duration="0:0:1" />
     </Storyboard>
    </BeginStoryboard>
   </EventTrigger>
  </Rectangle.Triggers>
 </Rectangle>

我猜如果你移除“width”数值,那么抖动就会发生,但是如果把数值放回去,它就会平稳运行。很奇怪。
是的,确实基本上需要通过数字规则的倍数对宽度进行一些调整,在这种情况下,动画可以是.1或.05,例如,如果你有5000个宽度....现在它运行得很好!

这篇CodeProject的文章很棒,但是它是针对WinForms的。不过没关系,还是很好的一篇文章。我使用了你的第一个答案来实现我想要的功能,并且通过一些调整使其运行得非常好。我使用了5000的宽度,调整了持续时间以使其更加平滑。同时将父元素的ClipToBounds属性标记为True。谢谢!附:我会在问题帖子中写下解决方案的模板。 - dbalboa
嗯,我以为是这样的。好吧,那我就把它移除掉。不过值得一提的是,WinForms 控件可以在 WPF 中托管。 - N_A

3
在您的PART_Indicator边框中嵌入一个复合路径,以制作对角线。但是,要使滚动对角线具有它所需的Marquee效果,您需要进行一些技巧操作,除非您想使用jquery插件或其他替代方法。
不过,在xaml中,您可以创建对角线路径,并制作大量这样的路径,使对角线行非常长。由于它们被嵌入到指示器边框中,因此只在其中可见。
现在创建一个新的故事板动画,并使用ControlStoryboardAction行为来在加载时触发它并设置为重复播放。选择时间轴上距离启动帧相当远的关键帧,然后将对角线复合路径拖到一侧或将左侧设置为大间距,以便在动画序列期间向右移动。这个想法实际上是一个视觉骗局。您的对角线只是一个动画故事板,只是模仿Marquee动画。因此,这些线条将在该栏中移动,希望有足够多的线条,动画才不会在内容加载之前重复。希望这讲得清楚。需要一些微调,但您可以得到一个不错的解决方案。祝您好运!

谢谢!最终理解了Mydogisbox的答案,不过你的想法也是正确的 ;) - dbalboa
没关系,只要你得到了答案,我在发布时没有注意到其他的。圣诞快乐! :) - Chris W.

1

这篇文章相当古老,但我刚刚遇到了同样的问题,并得到了一个不错的解决方案,我想分享一下:

  <SolidColorBrush x:Key="ProgressBarBackgroundBrush" Color="Gray" />
  <SolidColorBrush x:Key="ProgressBarTrackBackgroundBrush" Color="#105295" />
  <Style x:Key="{x:Type ProgressBar}" TargetType="{x:Type ProgressBar}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ProgressBar}">
                        <controls:RoundBorder x:Name="BorderBackground" CornerRadius="3" BorderThickness="0"
                        BorderBrush="{StaticResource ProgressBarBorderBrush}"
                        Background="{StaticResource ProgressBarBackgroundBrush}">
                            <Grid>
                                <VisualStateManager.VisualStateGroups>
                                    <VisualStateGroup x:Name="CommonStates">
                                        <VisualState x:Name="Determinate" />
                                        <VisualState x:Name="Indeterminate" />
                                    </VisualStateGroup>
                                </VisualStateManager.VisualStateGroups>
                                <Border x:Name="PART_Track" Margin="0" BorderThickness="0" CornerRadius="3"  />
                                <Border x:Name="PART_Indicator" Margin="0" BorderThickness="0" CornerRadius="3" HorizontalAlignment="Left"
                                Background="{StaticResource ProgressBarTrackBackgroundBrush}" ClipToBounds="True">
                                    <Border x:Name="DiagonalDecorator" Width="5000">
                                        <Border.Background>
                                            <DrawingBrush  TileMode="Tile" Stretch="None" Viewbox="0,0,1,1" Viewport="0,0,36,34"  ViewportUnits="Absolute">
                                                <DrawingBrush.RelativeTransform>
                                                    <TranslateTransform X="0" Y="0" />
                                                </DrawingBrush.RelativeTransform>
                                                <DrawingBrush.Drawing>
                                                    <GeometryDrawing Brush="#156dc7" Geometry="M0,0 18,0 36,34 18,34 Z" />
                                                </DrawingBrush.Drawing>
                                            </DrawingBrush>
                                        </Border.Background>
                                        <Border.Triggers>
                                            <EventTrigger RoutedEvent="FrameworkElement.Loaded">
                                                <BeginStoryboard>
                                                    <Storyboard>
                                                        <DoubleAnimation Storyboard.TargetProperty="(Border.Background).(DrawingBrush.RelativeTransform).(TranslateTransform.X)"
                                                    From="0" To=".36" RepeatBehavior="Forever" Duration="0:0:18" />
                                                    </Storyboard>
                                                </BeginStoryboard>
                                            </EventTrigger>
                                        </Border.Triggers>
                                    </Border>
                                </Border>
                            </Grid>
                        </controls:RoundBorder >
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

1
优秀的工作。这应该是被接受的答案。 - Jason Stevenson
@thardes2,你能否提供你答案的完整XAML文档版本吗?因为当我复制粘贴整个答案时,会出现XAML错误(无法在UIElementCollection中添加Style类型的值)。请注意,我将你的代码放在了一个网格中。 - NikSp
@NikSp - 对不起,我无法再访问那段代码片段了。 - thardes2
@thardes2 没关系。我正在尝试在C#中使用高级功能。感谢您的提醒。 - NikSp

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