Binary Bob’s Blog

3
Jun

Databind to an Attached Property? – guess not [update: Yes!]

Posted By Bob Bartholomay under C#, Silverlight.

[updated 7/12/09 to Silverlight 3 RTW]

[update 7/13/09 solution found thanks to Joe]

Many thanks to Joe Gershgorin for taking the time to post his comment(s) that explained how to get the Binding syntax right. I had tried using parentheses around the Attached Property previously but must have had something else amiss.

Here’s a blurb from Accellerated Silverlight 2 that explains it:

If you want to specify an attached property, however, it must be surrounded by parentheses.
This was shown earlier with the Canvas.Left property:
TargetProperty = “(Canvas.Left)”
The object to the left of the dot can be qualified with an XML namespace prefix if the class is
not located in the default XML namespace. The property to the right of the dot must be a dependency
property.

The original post is left intact as there are a few errors that now serve as learning points. At the bottom of this post are the updated bits and a working solution (thanks to Joe).

As a side note, learning new things is terrific. By trying to figure something out, having limited success, thinking about it constantly, and finally having the light go on is the best way to learn. You get it and you remember it after this type of learning.

[original post]

I am learning that when you want to use Silverlight classes, be sure to look over the docs to be sure its not sealed or that some of the properties you want to mess with are not ReadOnly. For instance, I wanted to instantiate a VisualStateGroup object (for a super secret project! ) but learned that the Name property has a private setter.

?View Code CSHARP
1
public string Name { get; }

I quickly created an Attached Property but soon ran into another “opportunity for learning”: You (apparently) cannot DataBind to an Attached Property.

I searched high and low for a definitive answer but found none. I posted on the Silverlight 3 Beta Forum but got no replies (so far). I could not find a direct way to bind to an attached property. If anyone has an idea how to bind to an attached property I will appreciate if you share it with me.

So the thing to do when figuring things out is to create as simple a test application as possible in an effort to isolate the issue(s). I created a new Silverlight 3 Application named BindToAttachedPropertyTest and created a simple boolean Attached Property as follows:

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
using System.Windows;
 
namespace BindToAttachedPropertyTest
{
    public class SimpleAttachedProperty
    {
       public static readonly DependencyProperty SimpleBooleanProperty = DependencyProperty.RegisterAttached(
            "SimpleBoolean",
            typeof( bool ),	
            typeof(SimpleAttachedProperty),
            null );	
 
       public SimpleAttachedProperty()
        {
        }
 
       public static void SetSimpleBoolean(DependencyObject obj, bool simpleBoolean)
        {
            obj.SetValue(SimpleBooleanProperty, simpleBoolean);
        }
 
       public static bool GetSimpleBoolean(DependencyObject obj)
        {
            return ( bool )obj.GetValue( SimpleBooleanProperty );
        }
    }
}

Then the MainPage.XAML tries to Bind the isChecked property of a Checkbox to this Attached Property:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<UserControl x:Class="BindToAttachedPropertyTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:BindToAttachedPropertyTest;assembly=BindToAttachedPropertyTest"
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="White">
        <StackPanel>
            <Button x:Name="button" Content="Togle Attached Property True/False"
                    Click="button_Click" local:SimpleAttachedProperty.SimpleBoolean="True"/>
            <CheckBox IsChecked="{ Binding SimpleAttachedProperty.SimpleBoolean, ElementName=button }"/>
            <TextBlock x:Name="textblockStats"/>
        </StackPanel>
 
    </Grid>
</UserControl>

The Button Click Event handler in the code behind toggles the boolean Attached Property true and false (which should be reflected in the Checkbox being checked and unchecked as its “bound”)

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System;
using System.Windows;
using System.Windows.Controls;
 
namespace BindToAttachedPropertyTest
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }
 
        private void button_Click(object sender, RoutedEventArgs e)
        {
            if (SimpleAttachedProperty.GetSimpleBoolean(this.button))
                SimpleAttachedProperty.SetSimpleBoolean(this.button, false);
            else
                SimpleAttachedProperty.SetSimpleBoolean(this.button, true);
 
            textblockStats.Text = "SimpleAttachedProperty is: " + SimpleAttachedProperty.GetSimpleBoolean(this.button).ToString();
        }
    }
}

The completed application is below. Either my Binding syntax is wrong (very possible) or you cannot bind to Attached Properties (but hey, its a Dependency Property!). Again, Can anyone enlighten me? – Cheers!

[update 7/13/09 Here's the working code and application

Here’s the updated SimpleAttachedProperty class:

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
 
namespace AttachedPropertyBindingTest
{
    public class SimpleAttachedProperty : DependencyObject
    {
        public static readonly DependencyProperty SimpleBooleanProperty = DependencyProperty.RegisterAttached(
             "SimpleBoolean",
             typeof(bool),
             typeof(SimpleAttachedProperty),
             null);
 
        public SimpleAttachedProperty()
        {
        }
 
        public static void SetSimpleBoolean(DependencyObject obj, bool simpleBoolean)
        {
            obj.SetValue(SimpleBooleanProperty, simpleBoolean);
        }
 
        public static bool GetSimpleBoolean(DependencyObject obj)
        {
            return (bool)obj.GetValue(SimpleBooleanProperty);
        }
 
    }
}

Here’s the MainPage XAML code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<UserControl x:Class="AttachedPropertyBindingTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:AttachedPropertyBindingTest"             
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
    <Grid x:Name="LayoutRoot" Background="White">
        <StackPanel>
            <Button x:Name="button"
                    HorizontalAlignment="Left"
                    Content="Toggle Attached Property True/False"
                    Click="button_Click"/>
            <CheckBox IsChecked="{ Binding
                Path=(local:SimpleAttachedProperty.SimpleBoolean),
                ElementName=button,
                Mode=TwoWay }" />
            <TextBlock Text="{ Binding
                Path=(local:SimpleAttachedProperty.SimpleBoolean),
                ElementName=button,
                Mode=OneWay }" />
        </StackPanel>
    </Grid>
</UserControl>

And here’s the code behind

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
 
namespace AttachedPropertyBindingTest
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }
 
        private void button_Click(object sender, RoutedEventArgs e)
        {
            if (SimpleAttachedProperty.GetSimpleBoolean(this.button))
                SimpleAttachedProperty.SetSimpleBoolean(this.button, false);
            else
                SimpleAttachedProperty.SetSimpleBoolean(this.button, true);
        }
    }
}

And finally the actual (working!) application:

Cheers!

3 Responses to “Databind to an Attached Property? – guess not [update: Yes!]”

  1. Joe Gershgorin said:

    In your sample application the binding does work, the button toggles the checkmark state, however clicking the checkmark breaks the binding, not sure on why that is, would have to look into it further.

  2. Joe Gershgorin said:

    This should fix the checkmark breaking the binding:

  3. Joe Gershgorin said:

    Hmm, let me try again, your comment system didn’t like tags…

    <CheckBox IsChecked=”{ Binding Path=(local:SimpleAttachedProperty.SimpleBoolean), ElementName=button, Mode=TwoWay }” />

Leave a Reply