A 'Binding' can only be set on a DependencyProperty of a DependencyObject
Asked Answered
B

7

69

From a custom control based on TextBox, I created a property named Items, in this way:

public class NewTextBox : TextBox
{
    public ItemCollection Items { get; set; }
}

When using the custom control in XAML, I cannot bind the property because it raises exception "A 'Binding' can only be set on a DependencyProperty of a DependencyObject.".

How do I solve this exception?

Barn answered 11/7, 2012 at 15:12 Comment(7)
Yes. Only Dependency properties can act as targets for bindings. Source could be a dependency property or a CLR property that implements INotifyPropertyChangedLotte
This is an exact duplicate of your other question, where you accept an answer and say "but I had to modify the property to include the DependencyProperty". Your solution should have been included as an answer thereChancellorsville
@AdamHouldsworth Yes, this question was posted just to post the answer. This is actually encouraged as it is seen as a form of sharing knowledge, and there is even a new CheckBox on the Ask Question form that will allow you to write an answer at the same time as you write your question.Round
@Round Fair enough, I didn't spot that as I haven't asked a question in a long time. Either way, I neither downvoted the question or the answer, so my hands are clean :-)Widescreen
@Chancellorsville Rachel has the right explanation. And I choose to post here instead of he old question as I see the binding problem as a different question from the DependencyProperty exception.Barn
@Round thanks for the explanation - i likewise haven't seen that checkbox beforeChancellorsville
Note also missing "static" for the DependencyProperty throws (obviously) this error.Undecided
F
125

As a side note, it is also worth noting that you will get these binding errors if you copy and paste between objects and forget to change the second typeof(Object) statement.

I couldn't figure out for a good hour why I was getting this error as everything appeared to be defined and correct. I'd moved my properties into a usercontrol as I wanted to go from a single set to a list. Thus:

public static readonly DependencyProperty FoldersProperty = DependencyProperty
    .Register("Folders", typeof(OutlookFolders), typeof(MainWindow),
    new FrameworkPropertyMetadata(new OutlookFolders()));

public OutlookFolders Folders
{
    get { return GetValue(FoldersProperty) as OutlookFolders; }
    set { SetValue(FoldersProperty, value); }
}

Should have become:

public static readonly DependencyProperty FoldersProperty = DependencyProperty
    .Register("Folders", typeof(OutlookFolders), typeof(SavedFolderControl), 
    new FrameworkPropertyMetadata(new OutlookFolders()));

public OutlookFolders Folders
{
    get { return GetValue(FoldersProperty) as OutlookFolders; }
    set { SetValue(FoldersProperty, value); }
}

Until I did this change I kept receiving the error: A 'Binding' cannot be set on the property 'Folders' of type 'SavedFolderControl'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.

Forwardness answered 21/11, 2013 at 11:3 Comment(4)
This. I copied a UserControl with some DependencyProperties and that means the old typeof(____)-Value still exists and is valid. I do not get any errors until runtime. And then XAML Parsing Exception "A Binding can only be set..." and so on. Thanks!Urushiol
It may exist but dot the types proposed types actually match.Forwardness
No, that's the point. I meant the class exist and is valid. So you won't get any errors in VS. Until you compile and run. But then you don't know where the error comes from! That was my mistyke after copying..Urushiol
Ah yes. That was what I did too. Only pinged in my head when I read about copying and pasting to check it thoroughly as that's what I'd done.Forwardness
B
32

To solve this exception you need to change the property Items and add a DependencyProperty that will work as a "link" in XAML. The class will be:

public class AutocompleteTextBox : TextBox
{
    public ItemCollection Items
    {
        get {
            return (ItemCollection)GetValue(ItemsProperty); }
        set {
            SetValue(ItemsProperty, value); }
    }

    public static readonly DependencyProperty ItemsProperty =
        DependencyProperty.Register(
            "Items",
            typeof(ItemCollection),
            typeof(AutocompleteTextBox),
            new PropertyMetadata(default(ItemCollection), OnItemsPropertyChanged));

    private static void OnItemsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        // AutocompleteTextBox source = d as AutocompleteTextBox;
        // Do something...
    }
Barn answered 11/7, 2012 at 15:12 Comment(0)
B
30

Here's another gotcha: Ensure that the string in the first argument of DependencyProperty.Register() matches the name of the related property.

public static readonly DependencyProperty ItemsProperty =
    DependencyProperty.Register(
        "TheItems", // This is wrong
        typeof(ItemCollection),
        typeof(AutocompleteTextBox),
        new PropertyMetadata(default(ItemCollection), OnItemsPropertyChanged));

I ran into this issue when I renamed my property without changing the string.

Bordy answered 12/9, 2014 at 10:27 Comment(3)
Make sure the name is "Items", not "ItemsProperty"Nonsense
You can use nameof(Items) in recent .NET versions to avoid this problem.Corelation
Thank you for posting this. I know this might seem like an obvious answer and it is, but in my case, when I was building out my code and my dependency properties, I mistakenly put nameof(SelectedItemProperty) instead of "nameof(SelectedItem" in my DP declaration. Now, I did not intentionally do this, but this tends to happen when one is copying and pasting like all over the place. When I was getting this error, I didn't think to check for typos in my declaration. I wasted on hour on this. Sometimes, the most obvious thing is the issue. Thanks again!Vally
S
13

One thing I noticed, and I am not sure it is mentioned anywhere, is that the name of your DependencyProperty must match your property name

If your property name is Items, then you DependencyProperty must be ItemsProperty

In my case, as soon as I matched them the error went away

Soundless answered 3/1, 2020 at 19:57 Comment(1)
Wow. I can't believe this fixed the warning. Makes absolutely no sense, but works. Despite the fact my bindings did work at runtime I kept seeing this warning until I changed my DependencyProperty variable name to have Property appended.Quotable
P
4

Another potential cause of this is when you provide a bad type for the default value in the metadata.
For instance:

new PropertyMetadata(default(ItemCollection), OnItemsPropertyChanged)

would throw this error if you wrote instead:

new PropertyMetadata(false, OnItemsPropertyChanged)

This can also happen if you are copying and pasting from a code source.

Plantaineater answered 14/7, 2014 at 0:19 Comment(0)
B
2

I had this issue due to a lack of oversight on my part. I wrote

<Button.Visibility>
   <MultiBinding Converter="{StaticResource mvbConverter}">
     <Binding Path="{Binding isActive}" />
     <Binding Path="{Binding isCashTransaction}" />
   </MultiBinding>
</Button.Visibility>

when instead i should've wrote

<Button.Visibility>
   <MultiBinding Converter="{StaticResource mvbConverter}">
     <Binding Path="isActive" />
     <Binding Path="isCashTransaction" />
   </MultiBinding>
</Button.Visibility>
Byler answered 1/1, 2021 at 14:25 Comment(0)
B
1

I had the (runtime + designtime) message:

An unhandled exception of type 'System.Windows.Markup.XamlParseException' occurred in PresentationFramework.dll

Additional information: A 'Binding' cannot be set on the 'Property' property of type 'Trigger'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.

Where I was smart enough to define a Trigger on a VM property..

// incorrect.. cannot have Trigger for VM property
<Trigger Property="{Binding IsExpanded}" Value="True">
  <Setter Property="Visibility" Value="Visible"/>
</Trigger>

Which should of course be a datatrigger (which uses Binding instead of Property)

<DataTrigger Binding="{Binding IsExpanded}" Value="True">
  <Setter Property="Visibility" Value="Visible"/>
</DataTrigger>

Triggers are typically for Controls (Button, TextBox, FrameworkElement etc.) properties.

Boling answered 28/11, 2017 at 9:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.