Just another WordPress.com weblog

Tip: Attached BindableRun

Filipe Fortes posted a nice example project recently that extends the <Run /> control in Windows Presentation Foundation and allows you to bind the Text property of the Run control, a feature that, as he mentions, didn’t make it into the release version of WPF.

The approach demonstrated by FIlipe works well, but I thought it would serve as a good example of where you might choose an alternative approach – that of using Attached Dependency Properties in WPF – and explain why you might consider using this option over inheritance. This should serve as a good example of how Attached Dependency Properties are used (even if they may not be the best option for this particular example – that’s up to you to decide).

First, have a read of Filipe’s post to give you some context:

Permalink to BindableRun

Using attached dependency properties, we could approach the problem by creating a static class named “BindableExtender”. We could then add an attached dependency property to our static class:

public static class BindableExtender {
    public static string GetBindableText(DependencyObject obj) {
        return (string)obj.GetValue(BindableTextProperty);
    }

    public static void SetBindableText(DependencyObject obj,
        string value) {
        obj.SetValue(BindableTextProperty, value);
    }

    public static readonly DependencyProperty BindableTextProperty =
        DependencyProperty.RegisterAttached("BindableText",
            typeof(string),
            typeof(BindableExtender),
            new UIPropertyMetadata(null,
                BindableTextProperty_PropertyChanged));

    private static void BindableTextProperty_PropertyChanged(
        DependencyObject dependencyObject,
        DependencyPropertyChangedEventArgs e) {
        if (dependencyObject is Run) {
            ((Run)dependencyObject).Text = (string)e.NewValue;
        }
    }
}

Now we can use it in our Window like this:

<Window
    x:Class="AttachedBindableRunExample.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:AttachedBindableRunExample"
    Title="This is the title" Height="100" Width="250"
    x:Name="_this"
    >
    <Grid>
        <TextBlock>
            <Run
                local:BindableExtender.BindableText
                  ="{Binding ElementName=_this, Path=Title}"
            />
        </TextBlock>
    </Grid>
</Window>

For those who have used custom IExtenderProviders in Windows Forms (I’m looking at you, Mitch), the benefits are very similar – we get the same functionality as the inheritance approach, without the disadantages that inheritance brings. In most commercial Windows Forms applications you work with, there ends up a number of customised standard controls, such as TextBoxes, Labels and Buttons, each with multiple spawns for different purposes. New developers joining the project can often be overwhelmed by the number of controls they have to pick from, and when you have a requirement that requires you to merge the functionality, changing that inheritance tree really isn’t much fun.

Using attached dependency properties, we can implement the additional functionality we need in classes external to the control, and allow developers to work with the standard framework elements they are already familiar with. When you couple this functionality with Styles and Control Templates in WPF, there aren’t very many situations where you ever need to subclass anything in WPF.

About these ads

Comments on: "Tip: Attached BindableRun" (4)

  1. Inspired by your post, I extended it in a simple way to include Tables here: http://www.wiredprairie.us/journal/2007/04/binding_a_table_in_a_flowdocum.html

    Thanks for your post.

  2. Devarajan said:

    I get this error “{”Collection was modified; enumeration operation may not execute.”}” when i use the BindableRun element more than once in my flow document – if i use only once it keeps quiet and works correct- any clues. ??? Actually the error is thrown when I try to bind the datacontext of flowdocument to my Custom Object. (Error is thrown only if the custom element is used more than once). Please clarify. Thanks. (find the xaml below)

    (FLOW DOCUMENT)
    This

    Agreement is entered into between Customer and Microsoft as of the effective date.

    Customer Information

    Customer ID:

    Telephone:

    Fax:

    Email:

    The personal information Customer provides in connection with
    this agreement will be used and protected according to the privacy statement available at

    http://licensing.microsoft.com.

  3. Thanks for the post. I was wondering if you could show me how you would use the BindableRun programatically.

  4. I think we have a solution to the “Collection was modified” issue:

    http://code.logos.com/blog/2008/01/data_binding_in_a_flowdocument.html

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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

Tag Cloud

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: