Colin Eberhardt's Technology Adventures

Declarative Dependency Property Definition with T4 + DTE

August 18th, 2009

UPDATE I have published a more up-to-date version of this code on codeproject, which allows you to automate the generation of much more than just dependency properties.

This blog post describes a technique for specifying WPF / Silverlight Dependency Properties declaritively via attributes as illustrated by the following example:

[DependencyPropertyDecl("Maximum", typeof(double), 0.0)]
[DependencyPropertyDecl("Minimum", typeof(double), 0.0)]
public partial class RangeControl : UserControl
{
    ...
}

At design-time the declarations are read via a T4 template and the required code is generated. For more information, read on …

A few months ago I wrote an article on codeproject about a technique for generating dependency properties via T4 templates. In brief; with this technique, you provide an XML description of your classes and their dependency properties, run the T4 template, and partial classes are generated which contain these properties – no more writing DP boiler plate code! For those of you who are unfamiliar with T4, it is a code generation engine which is built into Visual Studio, for a primer, I refer you to my codeproject article.

A few days back Daniel Vaughan published a blog post about using T4 templates to generate project meta-data. He demonstrated how this could be used to solve the age-old problem of hard-coded property name strings when implementing INotifyPropertyChanged. His solution uses both T4 and DTE – an automation library which allows you to programmatically access the items within your projects and solutions. Daniel’s blog post inspired me to revisit my DP code generation solution in order to simplify it and remove the need for the XML file.

My first step was to define a custom attribute which can be used to indicate that a class requires the template to generate a DP:

[AttributeUsage(AttributeTargets.Class , AllowMultiple = true)]
public class DependencyPropertyDecl : Attribute
{
    public DependencyPropertyDecl(string name, Type type, object defaultValue)
    {
        this.name = name;
        this.type = type;
        this.defaultValue = defaultValue;
    }
 
    public string name;
    public Type type;
    public object defaultValue;
}

With DTE it should be possible to inspect all the classes in the project, identifying those for which this attribute exists and generate the required DPs. However, looking at the DTE APIs this is not such an easy task, whilst the API defines a ‘base’ interface CodeElement from which CodeClass, CodeNamespace etc… derive, there is no unified concept of ‘Children’, also the Project and Solution are not CodeElements. In other words, in order to find all the classes in a solution you must recurse over a heterogeneous collection of classes and properties.

In order to ease the task of locating the classes within the project that have the DependencyPropertyDecl attribute associated, I created a simple Linq-to-DTE implementation:

public IEnumerable<CodeElement> CodeElementsInProjectItems(ProjectItems projectItems)
{
    foreach (ProjectItem projectItem in projectItems)
    {
        foreach(CodeElement el in CodeElementsInProjectItem(projectItem))
        {
            yield return el;
        }
    }
}
 
public IEnumerable<CodeElement> CodeElementsInProjectItem(ProjectItem projectItem)
{
    FileCodeModel fileCodeModel = projectItem.FileCodeModel;
 
    if (fileCodeModel != null)
    {
        foreach (CodeElement codeElement in fileCodeModel.CodeElements)
        {
            //WalkElements(codeElement, null);
            foreach(CodeElement el in CodeElementDescendantsAndSelf(codeElement))
            {
                yield return el;
            }
        }
    }
 
    if (projectItem.ProjectItems != null)
    {
        foreach (ProjectItem childItem in projectItem.ProjectItems)
        {
            foreach (CodeElement el in CodeElementsInProjectItem(childItem))
            {
                yield return el;
            }
        }
    }        
}
 
 
public IEnumerable<CodeElement> CodeElementsDescendants(CodeElements codeElements)
{
    foreach(CodeElement element in codeElements)
    {
        foreach (CodeElement descendant in CodeElementDescendantsAndSelf(element))
        {
            yield return descendant;                
        }
    }
}
 
public IEnumerable<CodeElement> CodeElementDescendantsAndSelf(CodeElement codeElement)
{
    yield return codeElement;
 
    CodeElements codeElements;
 
    switch(codeElement.Kind)
    {        
 
        /* namespaces */
        case vsCMElement.vsCMElementNamespace:
        {
            CodeNamespace codeNamespace = (CodeNamespace)codeElement;                                        
            codeElements = codeNamespace.Members;
            foreach(CodeElement descendant in CodeElementsDescendants(codeElements))
            {
                yield return descendant;                
            }
            break;
        }
 
        /* Process classes */
        case vsCMElement.vsCMElementClass:
        {            
            CodeClass codeClass = (CodeClass)codeElement;            
            codeElements = codeClass.Members;
            foreach(CodeElement descendant in CodeElementsDescendants(codeElements))
            {                
                yield return descendant;                
            }            
            break;    
        }        
    }    
}

There might be simpler way of achieving this, it is the first time I have created a recursive IEnumerable implementation, so please let me know if I have done something stupid! For a much more elegant solution to the problem of creating an IEnumerable implementation on a tree like structure via recursion have a look at this blog post by David Jade. However, as I mentioned earlier, the heterogeneous nature of the DTE API onto the project structure prohibits this method.

Anyhow, with this nasty IEnumerable implementation out of the way, we can use the power of Linq to provide a concise implementation of ‘Find all the classes in the solution which have one or more DependencyPropertyDecl attributes’, and perform the required code-gen as follows:

// for details of how the DTE 'project' is located see Daniel's blog post or the attached source of this blog.
var elements = CodeElementsInProjectItems(project.ProjectItems);
var classes = elements.Where(el => el.Kind == vsCMElement.vsCMElementClass)
                               .Cast<CodeClass>()
                               .Where(cl => Attributes(cl).Any(at => at.Name=="DependencyPropertyDecl"));
 
foreach(var clazz in classes)
{
    GenerateClass(clazz);
}

The GenerateClass function is a simple modification of the one I wrote for generating classes based on XML descriptions. In this implementation we acquire the CodeAttribute.Value property for each of our custom attribute instances and from there obtain the DP name, type and default value:

<#+
/// 
/// Generates a class along with its associated DPs
/// 
private void GenerateClass(CodeClass clazz)
{
    string classNamespace = clazz.Namespace.Name;
    string className =  clazz.Name;

    bool classRaisesPropertyChanged = false;

#>

namespace <#= classNamespace #>
{
    public partial class <#= className #> <#+ if(classRaisesPropertyChanged){ #>: INotifyPropertyChanged<#+ } #> 
    {
<#+
    var attributes = Attributes(clazz).Where(att => att.Name=="DependencyPropertyDecl");
    foreach(CodeAttribute attribute in attributes)
    {
        string[] attributeValues = attribute.Value.Split(',');
        
        string propertyName = attributeValues[0].Trim().Replace("\"","");
        string propertyType = attributeValues[1].Trim().Substring(7, attributeValues[1].Length - 9);
        string summary = null;
        string metadata = null;
        string defaultValue = attributeValues[2].Trim();
        string typeConverter = null;
        bool propertyChangedCallback = true;
        bool isAttached = false;
        #>

        #region <#= propertyName #>
        <#+        
        
        GenerateCLRAccessor(typeConverter, propertyType, propertyName, summary);
        
        bool handleDPPropertyChanged = propertyChangedCallback || classRaisesPropertyChanged;
        
        GenerateDependencyProperty(className, propertyType, defaultValue, propertyName,
                                   handleDPPropertyChanged, isAttached, metadata, summary);        
        
        if (handleDPPropertyChanged)
        {
            GenerateChangeEventHandler(className, propertyName, propertyChangedCallback, classRaisesPropertyChanged);
        } 
        
        if (isAttached)
        {
            GenerateAttachedPropertyAccessor(propertyName, propertyType);
        }
        #>        
        #endregion
    <#+
    } // end foreach dps

    if (classRaisesPropertyChanged)
    {
        GenerateINotifyPropertChangedImpl();
    }
    #> 
    }
}

<#+
}
#>

(please forgive the lack of syntax highlighting wordpress/codeproject do not support T4 templates!)

The GenerateCLRAccessor, GenerateDependencyProperty, … functions are re-used from my previous XML-based approach to DP generation.

For a simple demonstration of this approach, here is the complete implementation for a simple range control which has a Maximum and Minimum property, where if the user enters a Minimum which is greater that the Maximum, the values are swapped:

<UserControl x:Class="WpfDeclarativeDPCodeGen.RangeControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <StackPanel x:Name="LayoutRoot" Background="White" Orientation="Horizontal">
        <TextBox  Width="50" Text="{Binding Minimum}"/>
        <TextBlock Text=" : " VerticalAlignment="Center"/>
        <TextBox  Width="50" Text="{Binding Maximum}"/>
    </StackPanel>
</UserControl>
[DependencyPropertyDecl("Maximum", typeof(double), 0.0)]
[DependencyPropertyDecl("Minimum", typeof(double), 0.0)]
[TypeConverter(typeof(string))]
public partial class RangeControl : UserControl
{
    public RangeControl()
    {
        InitializeComponent();
    }
 
    /// <summary>
    /// If max is less than min, swap their values
    /// </summary>
    private void Swap()
    {
        if (Maximum < Minimum)
        {
            double swap = Minimum;
            Minimum = Maximum;
            Maximum = swap;
        }
    }
 
    partial void OnMaximumPropertyChanged(DependencyPropertyChangedEventArgs e)
    {
        Swap();
    }
 
    partial void OnMinimumPropertyChanged(DependencyPropertyChangedEventArgs e)
    {
        Swap();
    }
}

When using this approach the workflow is quite simple, create your class, add the DependencyPropertyDecl attributes, then execute the code generation template. The output is an accompanying partial class which contains the DP code itself, plus partial methods which can be implemented in order to perform logic when the property changes.

I have not-yet completely ported my XML-based DP generation templates to this new declarative approach, for example the DependencyPropertyDecl attribute needs to also indicate property meta-data, whether a property is attached etc … However, I thought I would share my ideas in case I didn’t get the time (or urge) to make a complete implementation.

I feel that this approach has great potential far beyond DP code generation, simple examples could include attributes that indicate that a T4 template should generate a ‘generic’ INotifyPropertyChanged or IEditableObject implementation, and of course, the more complex application-specific possibilities are endless.

You can download an example project containing the RangeControl above: WpfDeclarativeDpCodeGen.zip

Try adding new DependencyPropertyDecl attributes, and re-run the code generation template (right click CodeGen/GeneratedObjects.tt -> Run Custom Tool), and inspect the generated output – CodeGen/GeneratedObjects.cs.

Finally, thanks to Daniel Vaughan for the inspiration.

Regards,
Colin E.

The mini-ViewModel pattern

August 7th, 2009

The construction of a ViewModel is often seen as the standard technique for solving binding problems within WPF and Silverlight. However, the addition of a ViewModel adds complexity to your code. This post describes an alternative method where a mini-ViewModel is applied directly to the problem areas in the view, leaving the rest to use simpler, straightforward binding to business objects.

One of the features of WPF / Silverlight that appealed to me immediately when I started to learn it was the flexibility of the binding framework. The concepts of DataContext inheritence and flexibility of the value converters results in a lot less glue-code, which makes me a happy developer! However, it does not take long before you start finding examples that just dont fit with the framework and things start to get just little more complex. This blog post describes one such example.

The example used in this blog post is of a very simple application which displays a business card. The business object rendered by the application, ContactDetails, has a number of simple CLR properties. Constructing a UI for viewing this business object is very easy, simply create an instance of this object (in a real application this object might come from a database or web service) and set it as the DataContext of the view:

public Page()
{
    InitializeComponent();
 
    ContactDetails details = new ContactDetails()
    {
        Company = "Scott Logic Ltd.",
        Email = "ceberhardt@scottlogic.co.uk",
        URL = "http://www.scottlogic.co.uk",
        Country = "UK",
        FullName = "Colin Eberhardt",
        PhoneNumber = 4408452241930
    };
 
    this.DataContext = details;
}

We then create some simple XAML with UI elements that bind to the various propeties of our object …

<Grid x:Name="LayoutRoot" Background="White">
    <Border BorderBrush="LightGray" Background="White"  BorderThickness="1.5" CornerRadius="20"
        VerticalAlignment="Center" HorizontalAlignment="Center">
        <Border Margin="5" BorderBrush="LightGray" BorderThickness="1.5" CornerRadius="15">
            <Border.Background>
                <ImageBrush>
                    <ImageBrush.ImageSource>
                        <BitmapImage UriSource="back.jpg" />
                    </ImageBrush.ImageSource>
                </ImageBrush>
            </Border.Background>
 
            <StackPanel Orientation="Vertical" Margin="10">
                <TextBlock Text="{Binding FullName}"
                           FontSize="15"
                           FontWeight="Bold" />
                <Rectangle Stroke="DarkGray" HorizontalAlignment="Stretch"
                           StrokeThickness="0.5" Height="1"/>
                <TextBlock Text="{Binding Company}" Margin="0,10,0,0"/>
                <StackPanel Orientation="Horizontal" >
                    <TextBlock Text="e: "/>
                    <TextBlock Text="{Binding Email}" />
                </StackPanel>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="w: "/>
                    <HyperlinkButton Content="{Binding URL}"/>
                </StackPanel>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="p: "/>
                    <TextBlock Text="{Binding PhoneNumber}"/>
                </StackPanel>
            </StackPanel>
        </Border>
    </Border>
</Grid>

And we get a lovely looking business card:

card

One problem with the above example is the phone number, outputting the raw number ’4408452241930′ is not terribly readable, besides phone numbers have a standard format, in this case, the phone number would be represented as ‘+44 (0)845 2241930′. Also, let’s make the problem more interesting; you might want to highlight the international dialing code in a different colour, or, if the application is being used by a UK client, display the number in a local format without the international code ’0845 2241930′. So just how do we achieve this?

In order to break the number up into different blocks of text, with different colours (i.e. styles), we need to modify our view to have multiple TextBlocks mapped to the PhoneNumber property of our business object. The part of our view which renders the phone number is modified as follows:

<StackPanel Orientation="Horizontal">
    <TextBlock Text="p: "/>
    <TextBlock Text="... country code ..." Foreground="LightGray"/>
    <TextBlock Text="... area code ..."/>
    <TextBlock Text="... local number ..."/>
</StackPanel>

But just how exactly do we bind the properties of these business objects?

One approach would be to use a value converter for each binding in order to extract the required part of the number, for example a CountryCodeValueConverter could be implemented which grabs the first 2 digits of the number. However, this approach is a little inelligent in that it fragments our logic into a number of separate classes, furthermore, if we want country specific formatting this requires the use of multibindings, which can be rather cumbersome if over-used (for a Silverlight implementation of multi bindings see my blog post from earlier this year).

Another approach which is often used to tackle tricky binding problems is the use of the Model-View-ViewModel (MVVM) pattern. With this pattern, our ContactDetails object is the Model, we construct a ViewModel which is a UI-oriented abstraction of the Model and it is this which we bind to the View. WPF guru Josh Smith describes MVVM as “a value converter on steroids” in order to highlight the usefulness of the pattern in this context.

The basic approach used here is to bind your View to a ViewModel rather than binding it to the business object directly. The ViewModel is specific to the view and wraps the business object (i.e. Model), forwarding the property values and change notification to the View. This extra layer allows us to supplement the properties of the Model object, adding new computed properties which are specific to the View. In this case, these computed properties can be used to expose ‘country code’, ‘area code’, etc… to our View.

(This is a common pattern so I am not going to reproduce the code required here, however, if you are interested, the attached sourcecode accompanying this article contains a regular ViewModel version as well as a mini-ViewModel implementation)

Whilst this approach works, my issue with it is that it adds quite a bit of boiler-plate code for wrapping properties, forwarding events etc … The removal of this glue-code is the exact reason that I like WPF/Silverlight so much! The MVVM pattern is primarily for supporting the designer-developer paradigm and enabling unit testing of UI applications, in my opinion the use of MVVM for anything else is just plain wrong!

So, how can we solve the problem of providing a nicely formatted phone number without the pain of bashing out line-after-line line of boiler-plate MVVM code? My solution to the problem isn’t to dispose of the MVVM pattern altogether, rather, it is to localise its usage to just the problem area. The first step is to encapsulate the rendering of the phone number as a user control:

...
<StackPanel Orientation="Horizontal">
    <TextBlock Text="p: "/>
    <local:PhoneNumberControl Number="{Binding PhoneNumber}" />
</StackPanel>
...

… which probably makes sense anyway from a perspective of good design and code re-use!

Now that we have moved the phone number property within the PhoneNumberControl we have isolated the problem and can deal with it locally. We can create a PhoneNumberControlViewModel which splits the phone number up into its various components and bind this to the PhoneNumberControl.

The control’s ViewModel looks something like this:

public class PhoneNumberControlViewModel : INotifyPropertyChanged
{
    public PhoneNumberControlViewModel(PhoneNumberControl ctrl)
    {
        _ctrl = ctrl;
        ComputeProperties();
 
        // listen to property changes in the control (we are interested
        // in just the Number property)
        _ctrl.PropertyChanged += Control_PropertyChanged;
    }
 
    private PhoneNumberControl _ctrl;
 
    private string _countryCodeText;
 
    private string _areaCodeText;
 
    private string _localNumberText;
 
    public string CountryCodeText
    {
        get { return _countryCodeText; }
        set { _countryCodeText = value; OnPropertyChanged("CountryCodeText");  }
    }
 
    public string AreaCodeText
    {
        get { return _areaCodeText; }
        set { _areaCodeText = value; OnPropertyChanged("AreaCodeText"); }
    }
 
    public string LocalNumberText
    {
        get { return _localNumberText; }
        set { _localNumberText = value; OnPropertyChanged("LocalNumberText"); }
    }
 
    private void Control_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "Number" || e.PropertyName == "Country")
        {
            ComputeProperties();
        }
    }
 
    private void ComputeProperties()
    {
        string formattedNumber = _ctrl.Number.ToString();           
        CountryCodeText = "+" + formattedNumber.Substring(0, 2);
        AreaCodeText = " (" + formattedNumber.Substring(2, 1) + ")" + formattedNumber.Substring(3, 3);
        LocalNumberText = " " + formattedNumber.Substring(6);
    }
}

Note that here the ViewModel is ‘wrapping’ the PhoneNumberControl rather than an instance of some Business / Model object.

Now we just set our ViewModel as the DataContext for the View, as per the typical usage of this pattern:

public PhoneNumberControl()
{
    InitializeComponent();
 
    this.DataContext = new PhoneNumberControlViewModel(this);
}

… and it doesn’t work. If you try the above, you will find that the binding on the PhoneNumberControls Number property no longer works. So why is this? if you look back at where the PhoneNumberControl instance is defined in our business card’s XAML markup you see that its Number property is bound as follows:

<local:PhoneNumberControl Number="{Binding PhoneNumber}" />

The source of this binding is not explicitly set, so will default to using the DataContext of the PhoneNumberControl instance. However, we have just changed this DataContext in our constructor to something else … oops!

Solving this problem is actually quite simple, the PhoneNumberControl markup is as follows:

<UserControl x:Class="SLMiniViewModel.PhoneNumberControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel x:Name="LayoutRoot" Orientation="Horizontal">
        <TextBlock Text="{Binding CountryCodeText}" Foreground="DarkGray"/>
        <TextBlock Text="{Binding AreaCodeText}"/>
        <TextBlock Text="{Binding LocalNumberText}"/>
    </StackPanel>
</UserControl>

If we modify our binding to the ViewModel as follows:

public PhoneNumberControl()
{
    InitializeComponent();
 
    LayoutRoot.DataContext = new PhoneNumberControlViewModel(this);
}

The subtle difference being that the ViewModel is now bound to the StackPanel which is the root of our visual tree within the control. This means that the PhoneNumberControl DataContext is still inherited from the business card and is our business object instance, the DataContext switch to the ViewModel is now neatly tucked just within the PhoneNumberControls visual tree, and it is this DataContext which our TextBlocks will inherit and bind to.

The result is that we can now use our mini-ViewModel embedded within the PhoneNumberControl to expose properties which are more amenable to binding to our View:

card2

Whilst this is a quite trivial example, in real-world applications, more complex examples where the data representation within the View is dependant on a number of properties are quite common. The source code accompanying this article extends the example a little further by making the formatting dependant on a second property of the business object. This is the sort of problem that would either push you towards multi-binding and numerous fragmented value converters, or a ViewModel.

In conclusion, the use of a mini-ViewModel which is embedded within a UserControl allows you to solve tricky binding problems without being weighed down by rolling out the MVVM pattern across your entire View. I am not against the MVVM pattern in itself, however I do firmly believe that it should only be used to solve the problems which it is was specifically designed for, i.e. supporting the designer-developer workflow and unit testing.

You can download the source-code for this article: SLMiniViewModel.zip – this project contains both MVVM and mini-MVVM implementations (count the number of lines in the ViewModel and contrast it with the mini-ViewModel).

Regards, Colin E.