10

I' writing a control library. In this library there are some custom panels which are populated with user UIElements. Since every child element in my lib must have a "Title" property, I wrote the following:

// Attached properties common to every UIElement
public static class MyLibCommonProperties
{
    public static readonly DependencyProperty TitleProperty =
        DependencyProperty.RegisterAttached( 
            "Title", 
            typeof(String),
            typeof(UIElement), 
            new FrameworkPropertyMetadata(
                "NoTitle", new PropertyChangedCallback(OnTitleChanged))
            );

    public static string GetTitle( UIElement _target )
    {
        return (string)_target.GetValue( TitleProperty );
    }

    public static void SetTitle( UIElement _target, string _value )
    {
        _target.SetValue( TitleProperty, _value );
    }

    private static void OnTitleChanged( DependencyObject _d, DependencyPropertyChangedEventArgs _e )
    {
       ...
    }
}

Then, if I write this:

<dl:HorizontalShelf>
    <Label dl:MyLibCommonProperties.Title="CustomTitle">1</Label>
    <Label>1</Label>
    <Label>2</Label>
    <Label>3</Label>
</dl:HorizontalShelf>

everything works fine and the property gets the specified value, but if I try to bind that property to some other UIElement DependencyProperty like this:

<dl:HorizontalShelf>
    <Label dl:MyLibCommonProperties.Title="{Binding ElementName=NamedLabel, Path=Name}">1</Label>
    <Label>1</Label>
    <Label>2</Label>
    <Label Name="NamedLabel">3</Label>
</dl:HorizontalShelf>

an exception would be thrown: "A 'Binding' cannot be set on the 'SetTitle' property of type 'Label'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject."

What am I missing? Binding seems to work fine if instead of binding to "Name" I bind to some other attached property defined in MyLibCommonProperties.

Thanks in advance.

Trisped
  • 5,705
  • 2
  • 45
  • 58
Trap
  • 12,050
  • 15
  • 55
  • 67
  • Hi, MyLibCommonProperties must derive from DependecyObject –  Nov 11 '11 at 10:59
  • 1
    Just a guess, but change your Get/SetTitle first parameters to DependencyObject, not UIElement. Also while registering your Attache property the third parameter must be the owner of the attached property, not the desired target. Change it to MyLibCommonProperties. – dowhilefor Nov 11 '11 at 11:19
  • What is `HorizontalShelf`? Have you tried it in a `StackPanel` or similar built-in control instead? Everything else seems fine. I can only assume `HorizontalShelf` is a custom control that does not recognize its children as logical children. See here: http://kentb.blogspot.com/2008/10/customizing-logical-children.html – Kent Boogaart Nov 11 '11 at 13:40

1 Answers1

15

Replace the UIElement in your DependencyProperty definition to MyLibCommonProperties

public static readonly DependencyProperty TitleProperty =
    DependencyProperty.RegisterAttached( 
        "Title", 
        typeof(String),
        typeof(MyLibCommonProperties), // Change this line
        new FrameworkPropertyMetadata(
            "NoTitle", new PropertyChangedCallback(OnTitleChanged))
        );

I think it might be because the binding implicitly uses the parent class specified to call SetTitle() so it is calling Label.SetTitle() instead of MyLibCommonProperties.SetTitle()

I had the same issue with some custom TextBox properties. If I used typeof(TextBox) then I couldn't bind to the value, but if I used typeof(TextBoxHelpers) then I could

Rachel
  • 130,264
  • 66
  • 304
  • 490
  • Rachel this is not the first time one of your answers has helped me! (and I'm sure it won't be that last). Even after almost a decade. – StayOnTarget Apr 23 '20 at 13:36
  • @UuDdLrLrSs Oh wow I can't believe it's been almost a decade! Now I feel old lol I'm very glad my answers are still useful though! :) – Rachel May 04 '20 at 14:58