15

I want to attach a dependency property to specific controls only.

If that is just one type, I can do this:

public static readonly DependencyProperty MyPropertyProperty = DependencyProperty.RegisterAttached("MyProperty", typeof(object), typeof(ThisStaticWrapperClass));

public static object GetMyProperty(MyControl control)
{
    if (control == null) { throw new ArgumentNullException("control"); }

    return control.GetValue(MyPropertyProperty);
}

public static void SetMyProperty(MyControl control, object value)
{
    if (control == null) { throw new ArgumentNullException("control"); }

    control.SetValue(MyPropertyProperty, value);
}

(So: limit the Control type in the Get/Set-Methods)

But now I want to allow that property to get attached on a different type of Control, too.
You'd try to add an overload for both methods with that new type, but that fails to compile because of an "Unknown build error, Ambiguous match found."

So how can I limit my DependencyProperty to a selection of Controls?
(Note: In my specific case I need it for TextBox and ComboBox)

ordag
  • 2,497
  • 5
  • 26
  • 35
  • to clarify you get the error if you have two methods `SetMyProperty(TextBox control, object value)` and `SetMyProperty(ComboBox control, object value)`? If so, it may be a limitation of the attached property system. If so, there may be no other way around it other than to attach to the greatest common base class and throw an exception when it is attached to an unsupported control type... –  Jul 29 '11 at 14:19
  • @Will - yes, thats what i tried =( That'd be bad, so i have to first _"allow"_ it for all `Control`s ... – ordag Jul 29 '11 at 14:29

1 Answers1

8

Ambiguous match found.

...is normally thrown by GetMethod if there are multiple overloads and no type-signature has been specified (MSDN: More than one method is found with the specified name.). Basically the WPF-engine is only looking for one such method.

Why not check the type in the method body and throw an InvalidOperationException if it's not allowed?


Note however that those CLR-Wrappers should not include any code beside the setting and getting, if the propery is set in XAML they will be disregarded, try throwing an exception in the setter, it will not come up if you only use XAML to set the value.

Use a callback instead:

public static readonly DependencyProperty MyPropertyProperty =
    DependencyProperty.RegisterAttached
        (
            "MyProperty",
            typeof(object),
            typeof(ThisStaticWrapperClass),
            new UIPropertyMetadata(null, MyPropertyChanged) // <- This
        );

public static void MyPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
    if (o is TextBox == false && o is ComboBox == false)
    {
        throw new InvalidOperationException("This property may only be set on TextBoxes and ComboBoxes.");
    }
}
H.B.
  • 166,899
  • 29
  • 327
  • 400
  • Throwing an exception is a possible way to enforce this, but i'd loose the editor autocomplete support (in VS), because it still shows up for every control in that case. – ordag Jul 29 '11 at 14:44
  • You *sure* that `MyPropertyChanged` is called when binding in XAML? DP getters/setters (regular, not attached) are bypassed by the dependency property system. If this is also true for attached DPs, he'll need to throw whenever he is acting on the attached properties. –  Jul 29 '11 at 14:55
  • 2
    @Will: The callback will be called on all changes, be it via binding, setting in XAML or calling the Set-method. – H.B. Jul 29 '11 at 15:01
  • Oh, ok, I was already using the property changed callback for further operations. So I'm trying to filter out unwanted controls at this point. – ordag Jul 29 '11 at 15:07
  • @ordag: This is just one of the limitations of attached properties, i do not think there is much you can do about it. (Blend Interactivity also just throws exceptions if you try to attach a `TriggerAction` to something other than `T`) – H.B. Jul 29 '11 at 15:11
  • @H.B: To bad, overloading that get/set seemed so intuitive, but i'm going to use your solution, ty. – ordag Jul 29 '11 at 15:14
  • @H.B. is there a way to register the inherited property only to a specific type of element in the visual tree , for example attach only to TextBox type element , ? – eran otzap Apr 05 '13 at 22:40