Sunday, May 13, 2012

WPF Tip: Attached properties and bindings

Attached properties are a great way to extend capabilities of existing elements without the need to derive or otherwise tinker with those elements. Suppose we create an attached property that is a collection of objects of some particular kind. When that property changes, those objects are read, and that special functionality is applied. Here’s a hypothetical example of such a scheme:

public static class SomeHelper {
    public static DemoCollection GetData(DependencyObject obj) {
        return (DemoCollection)obj.GetValue(DataProperty);
    }
 
    public static void SetData(DependencyObject obj, DemoCollection value) {
        obj.SetValue(DataProperty, value);
    }
 
    public static readonly DependencyProperty DataProperty =
         DependencyProperty.RegisterAttached("Data", typeof(DemoCollection), typeof(SomeHelper), new UIPropertyMetadata(null, OnDataChanged));
 
    static void OnDataChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) {
        var coll = (DemoCollection)e.NewValue;
        // do something with collection
        foreach(var d in coll) {
            Trace.WriteLine(d.Text);
        }
    }

public class Demo : DependencyObject {
    public string Text {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }
 
    public static readonly DependencyProperty TextProperty =
         DependencyProperty.Register("Text", typeof(string), typeof(Demo), new UIPropertyMetadata(string.Empty));
 
}
 
public class DemoCollection : List<Demo> {
}

To summarize: The SomeHelper class defines the Data property which is of type DemoCollection, which is a List of Demo objects. The reason DemoCollection is defined and the code doesn’t use List<Demo> directly, is because WPF’s XAML does not support generics at this time. For each Demo object within the collection, its property Text is printed using Trace.WriteLine. In a real application, this is where the special code would be.

Let’s use that in a simple scenario:

<Grid>
    <local:SomeHelper.Data>
        <local:DemoCollection>
            <local:Demo Text="Hello" />
        </local:DemoCollection>
    </local:SomeHelper.Data>
</Grid>

The “local” XML prefix points to the namespace and assembly where the above types are defined. In this case, we should see “Hello” traced out to the Visual Studio debugger when running with the debugger. No surprise there.

Read more: Pavel's Blog
QR: Inline image 1

Posted via email from Jasper-Net