Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ProgressBar Theme with diagonal lines decorator

I want to decorate the WPF ProgressBar like the image below:

Current:

ProgressBar without decoration

Decorated:

ProgressBar with decoration

Also, those blank diagonal lines should move in marquee animation from left to right. At the moment i have this simple Style for the current appearance:

<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>

Anyone can help me to get it? I searched for it but maybe i missed the correct keywords to find something like this, at least i usually see (like at OS X progressbar) that this "decoration" is usually used.

Thanks in advance ;).


Solution template with the answer code a bit modified:

<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>
like image 478
dbalboa Avatar asked Dec 22 '11 14:12

dbalboa


3 Answers

Edit:

This article from codeproject.com has a working version of the "barber pole" progress bar. Search the article for "CandyCaneProgressPainter".

Previous answer:

This does almost exactly what you want. All you have to do to make it what you want is restrict the visibility of the rectangle to the percentage you want and change the height/width ratio.

The keywords you want are "storyboard", "animate" and "trigger"

Here is the xaml from the link with some comments from the link on making the animation smooth:

 <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>

I guess the jerking happens if you remove the "width" value, but if the value is put back it runs smooth. Weird.

Yup, indeed it basically needed a few adjustments with the multiples of the number rules the width in this case the animation can be a .1 or a .05 if for instance you have a 5000 width.... now it work great!

like image 106
N_A Avatar answered Oct 21 '22 03:10

N_A


In your PART_Indicator border embed a Compound Path of the shapes to make the diagonal lines. You're going to have to kind of fake the Marquee effect to get the scrolling diagonal lines however unless you want to use a jquery plugin or other alternative.

However what you CAN do in pure xaml is create the diagonal line paths, make lots and lots of them to make the row of diagnol lines very very long. Since they're embedded in the indicator border they're only visible within it.

Now create a new storyboard animation and use a ControlStoryboardAction Behavior to trigger it onload and set it to repeat. Grab the diagonal lines compound path an choose a keyframe on your timeline a ways out from the start frame, then drag the Compound Path of diagonal lines to one side or set a large Margin to the left so during the animation sequence it moves to the right. The idea is its a visual hoax. Your diagonal lines will just act as an animation storyboard that only mimics the marquee animation. So those lines will still move across the bar and hopefully theres enough of them the animation doesnt repeat before the content is loaded. Hopefully this makes sense haha. It takes some tweaking but you can result in a decent solution. Best of luck!

like image 28
Chris W. Avatar answered Oct 21 '22 04:10

Chris W.


This post is quite old, but I just faced the same problem and got a nice solution I would like to share:

  <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>
like image 38
thardes2 Avatar answered Oct 21 '22 03:10

thardes2