Colin Eberhardt's Technology Adventures

A Circular ProgressBar Style using an Attached ViewModel

February 7th, 2011

This blog post describes how to re-template the Silverlight ProgressBar control to render a circular progress indicator. This approach uses an attached view model to circumnavigate some of the limitations of the ProgressBar design.

This blog post describes the creation of the following funky styles for the ProgressBar (and a bit of a rant about just what is wrong with the way that ‘lookless’ controls work!)

If you get sick of the spinning, click the pause button!

Introduction

A few days ago I answered a question on stack overflow which asked How create a Circular Style progressbar? (sic)

The answer which I gave, and most people seemed to agree with, was that to achieve this you would have to create your own control from ‘scratch’. I was happy that my answer was accepted, but at the same time a little unhappy that this should be the right answer. After all, Silverlight / WPF give you the power to create ‘lookless’ controls, and what is a circular progress bar if it isn’t just another skin or ‘look’ for the regular progress bar?

What is wrong with the ProgressBar?

If you look at the documentation for styling / templating the ProgressBar you will find that this control expects the template to contain two elements, ProgressBarTrack and ProgressBarIndicator:

What the ProgressBar does is, when the template is applied, in OnApplyTemplate, it locates the elements with the given names in order to update the visual state of the UI. You can use Reflector (quick, while it is still free!) to see how the state of these elements is updated in the ProgressBar.SetProgressBarIndicatorLength method:

private void SetProgressBarIndicatorLength()
{
    double minimum = base.Minimum;
    double maximum = base.Maximum;
    double num3 = base.Value;
    if ((this.ElementTrack != null) && (this.ElementIndicator != null))
    {
        FrameworkElement parent = VisualTreeHelper.GetParent(this.ElementIndicator) as FrameworkElement;
        if (parent != null)
        {
            double num4 = this.ElementIndicator.Margin.Left + this.ElementIndicator.Margin.Right;
            Border border = parent as Border;
            if (border != null)
            {
                num4 += border.Padding.Left + border.Padding.Right;
            }
            else
            {
                Control control = parent as Control;
                if (control != null)
                {
                    num4 += control.Padding.Left + control.Padding.Right;
                }
            }
            double num5 = (this.IsIndeterminate || (maximum == minimum)) ? 1.0 : ((num3 - minimum) / (maximum - minimum));
            double num6 = Math.Max((double) 0.0, (double) (parent.ActualWidth - num4));
            this.ElementIndicator.Width = num5 * num6;
        }
    }
}

You can see in the above code that the various properties of the ElementTrack and ElementIndicator elements (the two named elements in the template) are being updated programmatically. This basically restricts the re-templating capabilities of the ProgressBar to ones where the ‘indicator’ element has a width which is some proportion of its parent element. That is not very lookless!

So what is so bad about creating your own circular progress indicator from scratch? Firstly, there is the issue of object-oriented design principles and re-use. Secondly, and in my opinion much more importantly, is how this affects skinning. Templating allows you to radically change your UI simply by applying a new set of styles, see for example the Silverlight Toolkit Themes. Styles can change the value of any property of an element (including its template) but they cannot change the class itself! So, if you create a circular progress bar as a new control, you cannot interchange it with the standard ProgressBar simply by applying a theme.

An Attached View Model

OK, rant over. Time to fix the problem!

A few months ago I blogged about how to create completely lookless controls using an attached view model. The basic concept behind this approach is that the control itself should not include any logic which is tightly-coupled to a particular template, or ‘look’. This logic is still required, but is instead introduced into the template by means of an attached view model.

Typically the elements within a control’s template inherit the same DataContext as the control itself, i.e. whatever business object or view model you have bound to your UI. With the attached view model approach, a view model is attached to the root element in the template. On attachment, this view model acquires a reference to the ProgressBar, in order to adapt its properties, making it easier to render a circular indicator, and sets itself as the DataContext of the child elements:

The view model is attached in XAMl as follows, as a result the DataContext of any element within the template is now the view model:

<ControlTemplate TargetType="ProgressBar">
  <Grid x:Name="LayoutRoot">
    <!-- attach the view model -->
    <local:CircularProgressBarViewModel.Attach>
      <local:CircularProgressBarViewModel/>
    </local:CircularProgressBarViewModel.Attach>
 
    <!-- the rest of the template now has CircularProgressBarViewModel as the DataContext -->
  </Grid>
</ControlTemplate>

Becoming Attached

The changed handler for the Attach property is given below. In summary, on attachment, the view model sets itself as the DataContext for the element it has been attached to. It then handlers the Loaded event which fires when the UI is fully constructed in order to locate the ProgressBar using Linq to VisualTree:

/// <summary>
/// Change handler for the Attach property
/// </summary>
private static void OnAttachChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
  // set the view model as the DataContext for the rest of the template
  FrameworkElement targetElement = d as FrameworkElement;
  CircularProgressBarViewModel viewModel = e.NewValue as CircularProgressBarViewModel;
  targetElement.DataContext = viewModel;
 
  // handle the loaded event
  targetElement.Loaded += new RoutedEventHandler(Element_Loaded);
}
 
/// <summary>
/// Handle the Loaded event of the element to which this view model is attached
/// in order to enable the attached
/// view model to bind to properties of the parent element
/// </summary>
static void Element_Loaded(object sender, RoutedEventArgs e)
{
  FrameworkElement targetElement = sender as FrameworkElement;
  CircularProgressBarViewModel attachedModel = GetAttach(targetElement);
 
  // find the ProgressBar and associated it with the view model
  var progressBar = targetElement.Ancestors<ProgressBar>().Single() as ProgressBar;
  attachedModel.SetProgressBar(progressBar);
}

Once the view model is associated with the progress bar, it is able to compute properties which assist in the creation of a circular template, e.g. the angle used to represent a particular progress value.

/// <summary>
/// Add handlers for the updates on various properties of the ProgressBar
/// </summary>
private void SetProgressBar(ProgressBar progressBar)
{
  _progressBar = progressBar;
  _progressBar.SizeChanged += (s, e) => ComputeViewModelProperties();
  RegisterForNotification("Value", progressBar, (d,e) => ComputeViewModelProperties());
  RegisterForNotification("Maximum", progressBar, (d, e) => ComputeViewModelProperties());
  RegisterForNotification("Minimum", progressBar, (d, e) => ComputeViewModelProperties());
 
  ComputeViewModelProperties();
}
 
 
/// Add a handler for a DP change
/// see: http://amazedsaint.blogspot.com/2009/12/silverlight-listening-to-dependency.html
private void RegisterForNotification(string propertyName, FrameworkElement element, PropertyChangedCallback callback)
{
 
  //Bind to a dependency property  
  Binding b = new Binding(propertyName) { Source = element };
  var prop = System.Windows.DependencyProperty.RegisterAttached(
      "ListenAttached" + propertyName,
      typeof(object),
      typeof(UserControl),
      new PropertyMetadata(callback));
 
  element.SetBinding(prop, b);
}

Thanks to Anoop for publishing a nice and simple method for registering for change notification of dependency properties (what a pain that DPs do not also implement the INotifyPropertyChanged pattern!).

Each time one of the properties on the progress bar changes, the following method updates a few of the CLR properties exposed by the attached view model:

/// <summary>
/// Re-computes the various properties that the elements in the template bind to.
/// </summary>
protected virtual void ComputeViewModelProperties()
{
  if (_progressBar == null)
    return;
 
  Angle = (_progressBar.Value - _progressBar.Minimum) * 360 / (_progressBar.Maximum - _progressBar.Minimum);
  CentreX = _progressBar.ActualWidth / 2;
  CentreY = _progressBar.ActualHeight / 2;
  Radius = Math.Min(CentreX, CentreY);
  Diameter = Radius * 2;
  InnerRadius = Radius * HoleSizeFactor;
  Percent = Angle / 360;
}

The complete XAML for one of the styled progress bars seen at the top of this blog post is given below. Here you can see how the various UI elements within the template are bound to the attached view model:

<Style TargetType="ProgressBar" x:Key="PieProgressBarStyle">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="ProgressBar">
        <Grid x:Name="LayoutRoot">
          <!-- attach the view model -->
          <local:CircularProgressBarViewModel.Attach>
            <local:CircularProgressBarViewModel HoleSizeFactor="0.75"/>
          </local:CircularProgressBarViewModel.Attach>
 
          <!-- a circular outline -->
          <Ellipse Width="{Binding Diameter}" Height="{Binding Diameter}"
                    HorizontalAlignment="Center" VerticalAlignment="Center"
                    Stroke="LightGray" Fill="Transparent"
                    StrokeThickness="0.3">
          </Ellipse>
 
          <!-- a pie-piece that indicates the progress -->
          <local:PiePiece CentreX="{Binding CentreX}" CentreY="{Binding CentreY}"
                          RotationAngle="0" WedgeAngle="{Binding Angle}"
                          Radius="{Binding Radius}" Fill="LightBlue"/>
 
          <!-- progress as a percent -->
          <Grid util:GridUtils.RowDefinitions="*,3.5*,*"
                util:GridUtils.ColumnDefinitions="*,3.5*,*">
            <TextBlock Text="{Binding Percent, StringFormat=0%}"
                        Foreground="DarkBlue"
                        FontWeight="Bold" FontSize="20"
                        Grid.Row="1" Grid.Column="1"
                        VerticalAlignment="Center" HorizontalAlignment="Center"/>
          </Grid>
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

(The template uses a PiePiece is a control I borrowed from a PieChart control I created a few years back, and the simplified Grid syntax)

We now have a circular ProgressBar! …

Segmented Progress Bar

For a bit of fun I extended the attached view model to allow for the easy construction of circular progress bar sthat are rendered as discrete segments. The SegmentedProgressBarViewModel, which is attached to the template exposes a collection of objects which allow the creation of a segmented indicator via an ItemsControl. For full details,download the blog sourcecode.

<Style TargetType="ProgressBar" x:Key="SegmentedProgressBarStyle">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="ProgressBar">
        <Grid x:Name="LayoutRoot">
          <!-- attach the view model -->
          <local:CircularProgressBarViewModel.Attach>
            <local:SegmentedProgressBarViewModel HoleSizeFactor="0.7"/>
          </local:CircularProgressBarViewModel.Attach>
 
          <!-- render the segments -->
          <ItemsControl ItemsSource="{Binding Segments}">
            <ItemsControl.ItemsPanel>
              <ItemsPanelTemplate>
                <Grid/>
              </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
              <DataTemplate>
                <Grid>
                  <!-- a grey segment -->
                  <local:PiePiece CentreX="{Binding Parent.CentreX}" CentreY="{Binding Parent.CentreY}"
                            RotationAngle="{Binding StartAngle}" WedgeAngle="{Binding WedgeAngle}"
                            Radius="{Binding Parent.Radius}" InnerRadius="{Binding Parent.InnerRadius}"
                            Fill="LightGray" Stroke="White" Opacity="0.5"/>
                  <!-- a blue segment, with an Opacity bound to the view model -->
                  <local:PiePiece CentreX="{Binding Parent.CentreX}" CentreY="{Binding Parent.CentreY}"
                            RotationAngle="{Binding StartAngle}" WedgeAngle="{Binding WedgeAngle}"
                            Radius="{Binding Parent.Radius}" InnerRadius="{Binding Parent.InnerRadius}"
                            Fill="DarkBlue" Stroke="White" Opacity="{Binding Opacity}"/>
                </Grid>
              </DataTemplate>
            </ItemsControl.ItemTemplate>                  
          </ItemsControl>
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

The above markup results in the following style:

The sourcecode for this blog includes a few other styles, including a ‘glass’ effect which was borrowed from Pete Brown’s blog post on Pie chart styling.

Sourcecode

You can download the full sourcecode for this blog post: CircularProgressBar.zip

Regards, Colin E.

Using CSS Selectors for Styling in WPF

March 11th, 2009

When I first encountered WPF I was really impressed by its styling and templating features which are more powerful than anything else I had previously seen for desktop software development. The property-value pairing within styles instantly reminded me of CSS, however the WPF styles lack the most powerful feature of CSS – the selector. This blog post describes an attached behaviour for styling WPF application using CSS selectors.

Let’s first look at the anatomy of CSS. A CSS stylesheet is composed of a number of rules, each rule is composed of a selector which provides a pattern which the CSS selector engine matches against the target HTML document to locate nodes which to apply the style to. The styling information itself is defined within a declaration block, which consists of a number of comma-separated declarations enclosed within braces. The declaration block looks quite similar to a style within WPF …

div {
   font-size: 10px;
}
<Style TargetType="TextBlock">
    <Setter Property="FontSize" Value="10"/>
</Style>

So let’s ignore the declaration block for the moment and concentrate on the interesting part, the CSS selector.

Selectors define a pattern which is matched, the information which the selector contains can include the element (tag) type, class or ID. More complex selectors might also include element attribute values or use pseudo-classes. We can easily find parallel concepts to these within WPF …

  • HTML element type (e.g. div, p, a) => dependency object type (e.g. TextBlock, Button)
  • HTML ID (#menu) => dependency object Name (e.g. x:Name=”menu”)
  • HTML class (.title) => attached class property (e.g. css:Css.Class=”menu”)

The only concept for which there really is no correspondent in WPF is CSS class. This can easily be introduced via an attached property.

So now that we have the concept mapping, all we need now is a CSS selector engine that can apply our selector in order to extract matching objects from our visual / logical tree. Luckily I found a .NET CSS selector engine implementation in codeplex called Fizzler, you can read about it on the authors blog, or go straight to codeplex to download it. The author of this engine, Colin Ramsay, had done a great job of the implementation and had also written an exhaustive set of unit tests. The engine itself was tightly coupled to HtmlDocumentNodes, however I was able to slide a simple interface between the selector engine and the HTML document types as follows:

public interface IDocumentNode
{
    IAttributeCollection Attributes { get; }
    List<IDocumentNode> ChildNodes { get; }
    IDocumentNode ParentNode { get; }
    IDocumentNode PreviousSibling { get; }
    string Id { get; }
    string Class { get; }
    string Name { get; }
    bool IsElement { get; }
}
 
public interface IAttributeCollection
{
    IAttribute this[string name] { get; }
}
 
public interface IAttribute
{
    string Value { get; }
}

Again, thanks to the extensive unit tests, this refactor only took ~ 40 minutes.

The next job was to create an implementation of the above interfaces that walks the visual / logical trees, both were pretty easy to implement using the LogicalTreeHelper and VisualTreeHelper classes. With these classes implemented, I was able to query the visual tree using selectors as follows:

SelectorEngine engine = new SelectorEngine();
IList<IDocumentNode> matchingNodes = engine.Parse(".form TextBlock.warning");
 
// apply the style to all matching nodes
foreach (DependencyObjectNode matchingNode in matchingNodes)
{
   ...
}

In the above example, the selector engine returns any TextBlock with the class ‘warning’, which is a descendant of any element with the class ‘form’. This is certainly a novel way of querying the visual tree!

The next step is to define the declaration block and apply the style which they define to any matching elements.

public class StyleDeclarationBlock : List<StyleDeclaration>
{
}
 
public class StyleDeclaration
{
    public string Property { get; set; }
    public object Value { get; set; }
}

We can construct style declarations within XAML as follows:

<css:StyleDeclarationBlock>
    <css:StyleDeclaration Property="BorderThickness" Value="2"/>
    <css:StyleDeclaration Property="BorderBrush" Value="Black"/>
    <css:StyleDeclaration Property="CornerRadius" Value="5"/>
    <css:StyleDeclaration Property="Margin" Value="10,10,10,10"/>
</css:StyleDeclarationBlock>

The process for applying a style is pretty straightforward, the only subtle complication is that styles, once applied are frozen (i.e. immutable). Therefore, each time an element is selected via our selector engine, we clone the existing style then merge it with the new one. See the attached source-code for details.

Putting it all together involves the creation of an Attached Behaviour which associates a stylesheet with an element within our XAML. When the element is loaded, the rules within the stylesheet are applied. Let’s look at a simple demo …

Here is a simple UI defined in XAML. Note the absence of any styling information:

<Grid>
    <Border css:Css.Class="form">                
        <StackPanel Orientation="Vertical">
            <TextBlock css:Css.Class="title" Text="User Details"/>
            <Grid VerticalAlignment="Top" >
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>    
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>  
 
                <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
 
                </Grid.RowDefinitions>        
 
 
                <TextBlock css:Css.Class="mandatory" Text="Name"/>
                <TextBox  css:Css.Class="mandatory" Grid.Column="1" Text="Anthony Gatto"/>
 
                <TextBlock Grid.Row="1" Text="Age"/>
                <TextBox Grid.Row="1"  Grid.Column="1" Text="36"/>
 
                <TextBlock Grid.Row="2" Text="Profession"/>
                <TextBox Grid.Row="2"  Grid.Column="1" Text="Performer"/>
 
                <Button Grid.Row="3" Grid.Column="1" >Submit</Button>
            </Grid> 
        </StackPanel>
    </Border>
</Grid>

The resulting UI looks like this:

no-style

Now we apply our stylesheet to the root element in our XAML:

<css:StyleSheet x:Key="cssStyles">
    <css:StyleSheet.Rules>
 
        <css:StyleRule Selector=".form Grid *" SelectorType="LogicalTree">
            <css:StyleRule.DeclarationBlock>
                <css:StyleDeclarationBlock>
                    <css:StyleDeclaration Property="Margin" Value="4,4,4,4"/>
                </css:StyleDeclarationBlock>
            </css:StyleRule.DeclarationBlock>
        </css:StyleRule>
 
        <css:StyleRule Selector=".form TextBlock.mandatory">
            <css:StyleRule.DeclarationBlock>
                <css:StyleDeclarationBlock>
                    <css:StyleDeclaration Property="Foreground" Value="Red"/>
                </css:StyleDeclarationBlock>
            </css:StyleRule.DeclarationBlock>
        </css:StyleRule>
 
        <css:StyleRule Selector="Border.form">
            <css:StyleRule.DeclarationBlock>
                <css:StyleDeclarationBlock>
                    <css:StyleDeclaration Property="BorderThickness" Value="2"/>
                    <css:StyleDeclaration Property="BorderBrush" Value="Black"/>
                    <css:StyleDeclaration Property="CornerRadius" Value="5"/>
                    <css:StyleDeclaration Property="Margin" Value="10,10,10,10"/>
                </css:StyleDeclarationBlock>
            </css:StyleRule.DeclarationBlock>
        </css:StyleRule>
 
        <css:StyleRule Selector=".form .title">
            <css:StyleRule.DeclarationBlock>
                <css:StyleDeclarationBlock>
                    <css:StyleDeclaration Property="HorizontalAlignment" Value="Stretch"/>
                    <css:StyleDeclaration Property="HorizontalContentAlignment" Value="Center"/>
                    <css:StyleDeclaration Property="Background" Value="DarkBlue"/>
                    <css:StyleDeclaration Property="Foreground" Value="White"/>
                    <css:StyleDeclaration Property="FontSize" Value="13"/>
                    <css:StyleDeclaration Property="Padding" Value="3,3,3,3"/>
                    <css:StyleDeclaration Property="FontWeight" Value="Bold"/>
                </css:StyleDeclarationBlock>
            </css:StyleRule.DeclarationBlock>
        </css:StyleRule>
 
    </css:StyleSheet.Rules>
</css:StyleSheet>
 
...
 
<Grid css:Css.StyleSheet="{StaticResource cssStyles}">

Which styles our WPF application as follows:

styled

Let’s look at those selector in a little more detail. The first one, <css:StyleRule Selector=".form Grid *" SelectorType="LogicalTree"> is quite interesting. Here we are selecting everything within the Grid within our form and applying a margin. Note that here we are using a selector on the logical tree, otherwise we will also match elements within the control template of our TextBoxes and Buttons and will hence apply the margin internally within these elements also. However, in other contexts the ability to be able to apply styles within a controls template is a powerful concept.

The next selector <css:StyleRule Selector=".form TextBlock.mandatory"> styles our mandatory fields, the others styling the form title and borders.

The above is a pretty simple demonstration. The Fizzler CSS engine implements most of the CSS2.1 selectors and also some CSS3, so much more complex selector logic is possible. You can also include multiple comma-separated selectors on a rule.

Currently this code is not what I would call production-ready. It is just an idea that has been bugging me for a while that I wanted to get out of my head and share. I think this approach has a number of merits and it overcomes some of the restrictions in WPF styling. It provides a much more flexible mechanism for styling your UI, WPF gives you explicit styles and implicit styles, neither of which match the power of the CSS selector. This approach also adds the ability to merge styles, so if an element is matched by multiple rules these styles are merged. Furthermore, this approach does not impose the restriction that styles must have a TargetType, if the matching element does not have a corresponding dependency property, it simply does not pick up that piece of style information.

However, this implementation is not quite complete. I have not considered how to apply styles to dynamically generated content, ItemsControls for example.

I would be very interested to hear peoples opinions on this idea. Do you thin kit has potential? Perhaps if it was ported to Silverlight – it could even include mapping rules form ‘real’ CSS documents so that your Silverlight application could share style information with the rest of the web page which hosts it. But that is a job for another day …

You can download the code for this blog post here: wpfcssstyling.zip

UPDATE – the concept of using CSS to style WPF and Silvelight applications has been discussed on the WPF Discisples Group.

Regards, Colin E.

Styling hard-to-reach elements in control templates with attached behaviours

February 10th, 2009

OK, the title of this blog post is not very snappy, but it is not an easy problem to describe in a few short words. Here’s the rub, the WPF DataGrid has a select-all button located in the top-left corner, just like Excel and many other grid controls / applications. However, with the default style, this button is barely visible and I would not be surprised if a user of the grid failed to see it.

select-all

Unfortunately restyling this button is not all that straightforward. The more complex WPF controls like the DataGrid and ListView typically expose the template used to construct, and the style applied to their various visual elements.  However, the DataGrid does not expose a style or template for the select-all button.

Fortunately, all is not lost. With WPF, if a control does not expose a style for one of its component parts, you can replicate and replace its entire template. Sometimes this approach feels a little heavy-handed … “I can’t seem to find a way to fit those flashy alloy wheels to my car, so I’ll just by a new car that already has the wheels I like”.

I want to explore a more lightweight approach.

Whilst it is usually preferable to modify a controls template from XAML, in cases like this, I prefer the more concise approach of modifying them in code-behind. In order to do this, you need to handle the FrameworkElement.Loaded event on the control whos template you wish to modify. This event is fired after the control’s visual tree has been constructed, to verify this add a breakpoint in the event handler and inspect the visual tree with Mole. The image below shows the visual tree of my DataGrid which I have expanded to locate the select-all button.

datagrid-mole

You can see that the button is the first element, four steps down the visual tree, therefore it should be easy to locate by walking the visual tree. Once it has been reached we can simply replace its template to the one which we desire:

private void Grid_Loaded(object sender, RoutedEventArgs e)
{
    DependencyObject dep = sender as DependencyObject;
 
    // Navigate down the visual tree to the button
    while (!(dep is Button))
    {
        dep = VisualTreeHelper.GetChild(dep, 0);
    }
    Button button = dep as Button;
 
    // apply our new template
    object res = FindResource("SelectAllButtonTemplate");
    button.Template = res as ControlTemplate
}

The template SelectAllButtonTemplate is simply defined as a resource of our Window.

This works just fine for our single grid, but what if we want to use the same trick on multiple DataGrids? (Besides, we have code-behind, which in WPF is a bit of a dirty word!).

The Attached Behaviour pattern is a useful WPF pattern that proves very useful in this situation. In brief, attached properties add state to a your WPF elements, whereas attached behaviours add behaviour. When an attached property becomes associated with a dependency object, an event is raised. We can handle this event and register handlers on the events of the object being attached to, in this case, our DataGrid’s Loaded event.

The following code is our attached behaviour in its entirety:

public static class DataGridStyleBehaviour
{
    #region attached property
 
    public static ControlTemplate GetSelectAllButtonTemplate(DataGrid obj)
    {
        return (ControlTemplate)obj.GetValue(SelectAllButtonTemplateProperty);
    }
 
    public static void SetSelectAllButtonTemplate(DataGrid obj, ControlTemplate value)
    {
        obj.SetValue(SelectAllButtonTemplateProperty, value);
    }
 
    public static readonly DependencyProperty SelectAllButtonTemplateProperty =
        DependencyProperty.RegisterAttached("SelectAllButtonTemplate",
        typeof(ControlTemplate), typeof(DataGridStyleBehaviour),
        new UIPropertyMetadata(null, OnSelectAllButtonTemplateChanged));
 
    #endregion
 
    #region property behaviour
 
    // property change event handler for SelectAllButtonTemplate
    private static void OnSelectAllButtonTemplateChanged(
        DependencyObject depObj, DependencyPropertyChangedEventArgs e)
    {
        DataGrid grid = depObj as DataGrid;
        if (grid == null)
            return;
 
        // handle the grid's Loaded event
        grid.Loaded += new RoutedEventHandler(Grid_Loaded);
    }
 
    // Handles the DataGrid's Loaded event
    private static void Grid_Loaded(object sender, RoutedEventArgs e)
    {
        DataGrid grid = sender as DataGrid;
        DependencyObject dep = grid;
 
        // Navigate down the visual tree to the button
        while (!(dep is Button))
        {
            dep = VisualTreeHelper.GetChild(dep, 0);
        }
        Button button = dep as Button;
 
        // apply our new template
        ControlTemplate template = GetSelectAllButtonTemplate(grid);
        button.Template = template;
    }
 
    #endregion
}

This attached property can be used as illustrated below, where we apply the SelectAllButtonTemplate from our Window’s resources to a DataGrid:

<Window ...
    Title="BBC News RSS" Height="300" Width="400">
 
    <Window.Resources>
        <XmlDataProvider x:Key="NewsFeed"
                     Source="http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/front_page/rss.xml"  
                     XPath="//item" />
 
        <ControlTemplate x:Key="SelectAllButtonTemplate" TargetType="{x:Type Button}">
            <Grid>
                <Rectangle  x:Name="Border"
                            Fill="Pink" 
                            SnapsToDevicePixels="True" />
                <Polygon   x:Name="Arrow"
                           HorizontalAlignment="Right"
                           VerticalAlignment="Bottom"
                           Margin="8,8,3,3"
                           Opacity="0.15"
                           Fill="Black"
                           Stretch="Uniform"
                           Points="0,10 10,10 10,0" />
            </Grid>            
        </ControlTemplate>
    </Window.Resources>
 
    <Grid>
        <dg:DataGrid Name="dataGrid" AutoGenerateColumns="False" 
                     local:DataGridStyleBehaviour.SelectAllButtonTemplate="{StaticResource SelectAllButtonTemplate}"
                     ItemsSource="{Binding Source={StaticResource NewsFeed}}" RowHeaderWidth="25">
            <dg:DataGrid.Columns>
                <dg:DataGridTextColumn Header="Title" Binding="{Binding XPath=title}" Width="*"/>
                <dg:DataGridHyperlinkColumn   Header="Url" Binding="{Binding XPath=link}" Width="*"/>
                <dg:DataGridTextColumn Header="Date" Binding="{Binding XPath=pubDate}" Width="*"/>
            </dg:DataGrid.Columns>
        </dg:DataGrid>
    </Grid>
</Window>

The result is a beautiful pink select-all button that I don’t think any user would miss in a hurry:

pinkbutton

And a clean code-behind file for our Window :-)

You can download the demo project for this blog post in the following zip file, wpfstylinghiddenelements.

One last thing … if you are implementing a WPF / Silverlight control, please expose the styles and templates for all component parts of your control!

Regards, Colin E.