Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XAML binding not working on dependency property?

I am trying (and failing) to do data binding on a dependency property in xaml. It works just fine when I use code behind, but not in xaml.

The user control is simply a TextBlock that bind to the dependency property:

<UserControl x:Class="WpfTest.MyControl" [...]>
     <TextBlock Text="{Binding Test}" />
</UserControl>

And the dependency property is a simple string:

public static readonly DependencyProperty TestProperty 
= DependencyProperty.Register("Test", typeof(string), typeof(MyControl), new PropertyMetadata("DEFAULT"));

public string Test
{
    get { return (string)GetValue(TestProperty); }
    set { SetValue(TestProperty, value); }
}

I have a regular property with the usual implementation of INotifyPropertyChanged in the main window.

private string _myText = "default";
public string MyText
{
   get { return _myText; }
   set {  _myText = value; NotifyPropertyChanged(); }
}

So far so good. If I bind this property to a TextBlock on the main window everything works just fine. The text update properly if the MyText changes and all is well in the world.

<TextBlock Text="{Binding MyText}" />

However, if I do the same thing on my user control, nothing happens.

<local:MyControl x:Name="TheControl" Test="{Binding MyText}" />

And now the fun part is that if I do the very same binding in code behind it works!

TheControl.SetBinding(MyControl.TestProperty, new Binding
{
    Source = DataContext,
    Path = new PropertyPath("MyText"),
    Mode = BindingMode.TwoWay
});

Why is it not working in xaml?

like image 644
Oliver Avatar asked Oct 21 '16 19:10

Oliver


People also ask

How does binding work in XAML?

Data binding is a mechanism in XAML applications that provides a simple and easy way for Windows Runtime Apps using partial classes to display and interact with data. The management of data is entirely separated from the way the data is displayed in this mechanism.

What is a dependency property in XAML?

A dependency property is a specific type of property where the value is followed by a keen property system which is also a part of the Windows Runtime App. A class which defines a dependency property must be inherited from the DependencyObject class.

What is two way binding XAML?

TwoWay binding causes changes to either the source property or the target property to automatically update the other.

What is the default binding mode in WPF?

Default Data-binding It just defines which is the default binding mode for the control's property. In WPF different controls has different default data-binding modes. For example, TextBlock's Text property has one-way as default binding mode but a TextBox's Text property has a two-way binding mode.


1 Answers

The dependency property declaration must look like this:

public static readonly DependencyProperty TestProperty =
    DependencyProperty.Register(
        nameof(Test),
        typeof(string),
        typeof(MyControl),
        new PropertyMetadata("DEFAULT"));

public string Test
{
    get { return (string)GetValue(TestProperty); }
    set { SetValue(TestProperty, value); }
}

The binding in the UserControl's XAML must set the control instance as the source object, e.g. by setting the Bindings's RelativeSource property:

<UserControl x:Class="WpfTest.MyControl" ...>
     <TextBlock Text="{Binding Test,
         RelativeSource={RelativeSource AncestorType=UserControl}}"/>
</UserControl>

Also very important, never set the DataContext of a UserControl in its constructor. I'm sure there is something like

DataContext = this;

Remove it, as it effectively prevents inheriting a DataContext from the UserConrol's parent.

By setting Source = DataContext in the Binding in code behind you are explicitly setting a binding source, while in

<local:MyControl Test="{Binding MyText}" />

the binding source implicitly is the current DataContext. However, that DataContext has been set by the assignment in the UserControl's constructor to the UserControl itself, and is not the inherited DataContext (i.e. the view model instance) from the window.

like image 79
Clemens Avatar answered Nov 10 '22 22:11

Clemens