0

I am attempting to get to grips with DataBinding, and I have just started to introduce UserControls into the mix, but it appears I cannot even get the most basic example working.

I have a MainWindow that contains a property (Subtitle) along with an instance of a UserControl. A property of the UserControl (LabelContent) is bound to the Subtitle property. The expected result is that changing the Subtitle property of MainWindow will update the LabelContent property of the UserControl, which is bound to the actual Content property of a Label within the UserControl:

I have MainWindow.xaml:

<Window x:Class="WpfApp1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApp1"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<local:UserControlSample LabelContent="{Binding Subtitle}"/>

With the following code behind (MainWindow.cs):

public partial class MainWindow : Window
{

    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
        Subtitle = "Test";
    }

    public String Subtitle
    {
        get;
        set;
    }

}

UserControlSample.xaml:

<UserControl x:Class="WpfApp1.UserControlSample"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:WpfApp1"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="800">
<Label Content="{Binding Path=LabelContent}"/>

UserControl.cs:

public partial class UserControlSample : UserControl
{

    public static DependencyProperty LabelContentProperty = DependencyProperty.Register("LabelContent", typeof(String), typeof(UserControlSample));

    public UserControlSample()
    {
        InitializeComponent();
        DataContext = this;
    }

    public String LabelContent
    {
        get { return (String)GetValue(LabelContentProperty); }
        set { SetValue(LabelContentProperty, value); }
    }

}

I believe it is something to do with DataContexts however I do not understand them too well as yet. If I change UserControl to the following, then I achieve the expected results. However this does not explain the reasons why the original code fails:

UserControlSample.xaml
<Label Content="{Binding Path=Subtitle}"/>

UserControl.cs
public UserControlSample()
{
    InitializeComponent();
}
  • Besides the problem with setting the UserControl's DataContext (as explained in the answer to the duplicate question), you also need to set the Subtitle property before setting the Window's DataContext. If you want to be able to change it later, it must fire some kind of change notification, e.g. the PropertyChanged event from the INotifyPropertyChanged interface. – Clemens Feb 10 '19 at 10:19
  • Is there any chance you could expand the second part of your comment (setting the Subtitle property) into an answer? –  Feb 10 '19 at 10:23
  • That's not necessary. Your main problem is already addressed by the answers to the duplicate questions. And there are many more similar question on StackOverflow. – Clemens Feb 10 '19 at 10:25

1 Answers1

0

You would need changes at two places,

First in Xaml, you need to set the source object of the Binding to the UserControl

<Label Content="{Binding Path=LabelContent,RelativeSource={RelativeSource AncestorType=UserControl}}" />

Secondly,

 public UserControl1()
 {
      InitializeComponent();
 }

That should allow you to bind the User Control correctly

Anu Viswan
  • 17,797
  • 2
  • 22
  • 51
  • Thank you so much! If you have some free time at some point, would you mind returning to this answer to explain exactly what is happening and why I must remove DataContext=this from the UserControlSample constructor? Thank you. –  Feb 10 '19 at 10:18
  • @ILickWindows `` expects the Subtitle property in the current DataContext. If you set the DataContext of the UserControl to itself, the Binding won't work anymore. – Clemens Feb 10 '19 at 10:23