62

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?

mgottschild
  • 1,015
  • 1
  • 9
  • 10
  • 2
    Yes. Only Dependency properties can act as targets for bindings. Source could be a dependency property or a CLR property that implements INotifyPropertyChanged – Gishu Jul 11 '12 at 15:16
  • 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 there – arserbin3 Jul 11 '12 at 15:38
  • 6
    @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](http://meta.stackexchange.com/questions/132886/what-is-this-answer-your-own-question-jazz) that will allow you to write an answer at the same time as you write your question. – Rachel Jul 11 '12 at 15:56
  • @Rachel 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 :-) – Adam Houldsworth Jul 11 '12 at 15:58
  • 1
    @arserbin3 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. – mgottschild Jul 11 '12 at 16:29
  • @Rachel thanks for the explanation - i likewise haven't seen that checkbox before – arserbin3 Jul 11 '12 at 19:45

7 Answers7

121

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.

Soleil
  • 6,404
  • 5
  • 41
  • 61
netniV
  • 2,328
  • 1
  • 15
  • 24
  • 11
    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! – ecth Aug 02 '16 at 07:22
  • It may exist but dot the types proposed types actually match. – netniV Aug 02 '16 at 07:24
  • 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.. – ecth Aug 02 '16 at 11:02
  • 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. – netniV Aug 02 '16 at 11:27
30

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...
    }
Josef
  • 2,869
  • 2
  • 22
  • 23
mgottschild
  • 1,015
  • 1
  • 9
  • 10
29

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.

Oliver
  • 11,297
  • 18
  • 71
  • 121
  • 10
    Make sure the name is "Items", not "ItemsProperty" – Jeson Martajaya May 13 '15 at 17:51
  • 16
    You can use nameof(Items) in recent .NET versions to avoid this problem. – Herman Feb 18 '16 at 09:25
  • 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! – Ryan Aug 07 '22 at 17:36
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

Pic Mickael
  • 1,244
  • 19
  • 36
  • 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. – WSC Oct 29 '20 at 11:47
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.

Prof Von Lemongargle
  • 3,658
  • 31
  • 29
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>
RamWill
  • 288
  • 1
  • 3
  • 6
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.

EricG
  • 3,788
  • 1
  • 23
  • 34