Professional, Software

Templates for ProgressBar

After creating a ProgressBar Control, I wanted to make it look completely different. I am not sure where I am going to use it yet but point more was about trying to see how different can I make this control look using Templating. It should be something just Styling would not have been useful for.

I wanted to have a searchlight effect while I am downloading something (just to use the same example from my Live Search Sample). It means I wanted it to look something like below. Also during Value is being changed, I wanted the brush that shows the focus effect to rotate in circular motion.


Defining a Control Template

For defining a control template, you really need to know what are the parts and what the behavior of the control is. Since we don’t have tools yet, one could reflect over the assembly to get this information

Parts of Control
   1: [TemplatePart(Name = "PART_Indicator", Type = typeof(FrameworkElement))]
   2: [TemplatePart(Name = "PART_Value", Type = typeof(TextBlock))]
   3: [TemplatePart(Name = "STATE_InDeterminate", Type = typeof(Storyboard))]
   4: [TemplatePart(Name = "STATE_InProgress", Type = typeof(Storyboard))]

This tells me I need a Part called PART_Indicator of type FrameworkElement (or it is child classes), I also need Part called PART_Value of type TextBlock and then I need to define animations for “InProgress” and “IsInDeterminate” state.

Define the new looks

Using this information, I need to define a new visual for the control. This is what the new XAML for new look looks like

   1: <Grid x:Name="LayoutRoot">
   2:                 <Grid.RowDefinitions>
   3:                     <RowDefinition Height="{TemplateBinding Height}"/>
   4:                 </Grid.RowDefinitions>
   5:                 <Grid.ColumnDefinitions>
   6:                     <ColumnDefinition Width="{TemplateBinding Width}"/>
   7:                 </Grid.ColumnDefinitions>
   8:                 <Grid.Resources>
   9:                     <Storyboard x:Name="STATE_InDeterminate"
  10:                                 AutoReverse="False" RepeatBehavior="Forever">
  11:                         <PointAnimationUsingKeyFrames
  12:                             Storyboard.TargetName="PART_Indicator"
  13:                             Storyboard.TargetProperty="(Border.Background).(RadialGradientBrush.GradientOrigin)">
  14:                             <SplinePointKeyFrame KeyTime="00:00:01" Value="0.99,0.5"/>
  15:                             <SplinePointKeyFrame KeyTime="00:00:02" Value="0.5,0.99"/>
  16:                             <SplinePointKeyFrame KeyTime="00:00:03" Value="-0.015,0.505"/>
  17:                             <SplinePointKeyFrame KeyTime="00:00:04" Value="0.505,0.035"/>
  18:                         </PointAnimationUsingKeyFrames>
  19:                         <DoubleAnimationUsingKeyFrames
  20:                             Storyboard.TargetName="PART_Value"
  21:                             Storyboard.TargetProperty="(UIElement.Opacity)">
  22:                             <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
  23:                         </DoubleAnimationUsingKeyFrames>
  24:                     </Storyboard>
  25:                     <Storyboard x:Name="STATE_InProgress" RepeatBehavior="Forever">
  26:                         <PointAnimationUsingKeyFrames
  27:                             Storyboard.TargetName="PART_Indicator"
  28:                             Storyboard.TargetProperty="(Border.Background).(RadialGradientBrush.GradientOrigin)">
  29:                             <SplinePointKeyFrame KeyTime="00:00:01" Value="0.99,0.5"/>
  30:                             <SplinePointKeyFrame KeyTime="00:00:02" Value="0.5,0.99"/>
  31:                             <SplinePointKeyFrame KeyTime="00:00:03" Value="-0.015,0.505"/>
  32:                             <SplinePointKeyFrame KeyTime="00:00:04" Value="0.505,0.035"/>
  33:                         </PointAnimationUsingKeyFrames>
  34:                         <DoubleAnimationUsingKeyFrames
  35:                             Storyboard.TargetName="PART_Value"
  36:                             Storyboard.TargetProperty="(UIElement.Opacity)">
  37:                             <SplineDoubleKeyFrame KeyTime="00:00:00" Value="100"/>
  38:                         </DoubleAnimationUsingKeyFrames>
  39:                     </Storyboard>
  40:                 </Grid.Resources>
  41:                 <Border x:Name="PART_Indicator"
  42:                         MinWidth="{TemplateBinding Width}"
  43:                         MinHeight="{TemplateBinding Height}">
  44:                     <Border.Background>
  45:                         <RadialGradientBrush GradientOrigin="0.495,0.023">
  46:                             <GradientStop Color="#FF000000" Offset="1"/>
  47:                             <GradientStop Color="#FFFFFFFF" Offset="0"/>
  48:                         </RadialGradientBrush>
  49:                     </Border.Background>
  50:                 </Border>
  52:                 <TextBlock x:Name="PART_Value"
  53:                            HorizontalAlignment="Center" VerticalAlignment="Center"
  54:                            FontWeight="Bold" FontSize="24" FontFamily="Georgia"
  55:                            Foreground="#FF31D900" />
  56:             </Grid>

This is the actual look of the control.

Consume the Template

To consume this visual look inside my application. I need to do two things…

Define this Control Template in Resources

This XAML is wrapped in ControlTemplate Tag and given a Key

<ControlTemplate x:Key="ProgressBarTemplate">
Set the Template Property to Resource
   1: <control:ProgressBar x:Name="progress1"
   2:                              Style="{StaticResource TemplatedProgressBarStyle}"
   3:                              Template="{StaticResource ProgressBarTemplate}"
   4:                              Margin="10,10,10,10"
   5:                              Grid.Row="0" Grid.Column="0"/>

Here is the working project.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s