Search
Close this search box.

Binding to an Attached Property

Yesterday, I have some ideas in my mind on how to give out ValidationRule errors after the values passes the converter, and I was trying to see if I can use Attached Properties for that.

When trying to do this, one of the things I’d like to do was set a control’s text to the Attached Property’s value and that’s when I realized that I don’t know the syntax to do that.

A quick Google search yields some results; someone asked the same question and the answer suggested using parentheses.  The following example where the TextBox will display the row index the textbox is residing show how this works:


Bind to Grid.Row attached property

<Grid>

    <Grid.RowDefinitions>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="Auto"/>

    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>

        <ColumnDefinition/>

    </Grid.ColumnDefinitions>

    <TextBox Text="{Binding (Grid.Row),RelativeSource={RelativeSource Self}}"

             Height="23" Grid.Column="0" Grid.Row="0" VerticalAlignment="Top" />

    <TextBox Text="{Binding (Grid.Row),RelativeSource={RelativeSource Self}}"

             Height="23" Grid.Column="0" Grid.Row="1" VerticalAlignment="Top" />

    <TextBox Text="{Binding (Grid.Row),RelativeSource={RelativeSource Self}}"

             Height="23" Grid.Column="0" Grid.Row="2" VerticalAlignment="Top" />

    <TextBox Text="{Binding (Grid.Row),RelativeSource={RelativeSource Self}}"

             Height="23" Grid.Column="0" Grid.Row="3" VerticalAlignment="Top"

             Name=”textBox4” />

</Grid>

You can also see that I didn’t use Path=(Grid.Row), by default the first parameter is assigned to the Path property of the Binding class.

What about if we want to do it in code; it’s very similar: 


Binding b = new Binding("(Grid.Row)");

b.Source = textBox4;

BindingOperations.SetBinding(textBox4, TextBox.TextProperty, b);

The binding path is the same; (Grid.Row) and the other important tidbit is that the source is the textbox itself.  This is logical since when assigning a value to an Attached Property, you’re assigning that value for a given DependencyObject.  In this case, we want the text to be set to the Grid.Row attached property for that particular textbox too.

Verifying that it works, now I continue on with my class that implements the Attached Property.  However, since I need to refer to my class using XML namespace, how would the Path look?  The path has to use the namespace too, as the sample below shows:


<Grid xmlns:local="clr-namespace:BindingToAttachedProperty">

    <Grid.RowDefinitions>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="Auto"/>

    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>

        <ColumnDefinition/>

    </Grid.ColumnDefinitions>

    <TextBox Text="{Binding Path=(local:LocalClass.SomeValue),RelativeSource={RelativeSource Self}}"

             local:LocalClass.SomeValue="1"

             Height="23" Grid.Column="0" Grid.Row="0" Vertical.Alignment="Top" />

    <TextBox Text="{Binding (local:LocalClass.SomeValue),RelativeSource={RelativeSource Self}}"

             local:LocalClass.SomeValue="2"

             Name="textBox2"

             Height="23" Grid.Column="0" Grid.Row="1" VerticalAlignment="Top" />

</Grid>

I found a weird condition in WPF; you can see that for the first TextBox, the Binding has the Path=, while the second one doesn’t.  The sample above works, the first textbox will display 1, and the second textbox will display 2.  However, if you take out that Path= string, the example will not work; the BindingExpression specifies PathError.  I believe this is because without the first Path=, WPF doesn’t know what is (local:LocalClass.SomeValue).  By specifying Path=, WPF compiles it correctly, and the subsequent encounter of (local:LocalClass.SomeValue) in textBox2 results in a correct interpretation.

OK, the XAML works; how to do it in code?  I tried all kinds of combination for the path, and could not get anything to work – it took me about 2 hours trying around and finally I got a solution.

Binding b = new Binding();

b.Path = new PropertyPath(LocalClass.SomeValueProperty);

b.Source = textBox2;

BindingOperations.SetBinding(textBox2, TextBox.TextProperty, b);

Most of the time, people will just create a new Binding instance, passing the string path in its constructor.  I could not get this to work; all types of string values that I tried results in PathError.  Finally, I took a good look at the Path property in the Binding class and found that one of the PropertyPath constructor accepts an object parameter that can be a DependencyProperty.

This would be my first ‘New Thing I Learned’ to document .  I’m sure I will look at this information again in the future, and I hope other people can benefit from this.

This article is part of the GWB Archives. Original Author: Muljadi Budiman

Related Posts