user1102760
user1102760

Reputation: 25

Why DataContext for inner object is not updated?

I have question about DataContext changes and I build example for understand this aspect. I have MainUserControl on MainWindow. MainUserControl consists of number of User Controls. One of such User Controls is SubUserControl1.

<Window x:Class="WpfApplicationUcBindingQuestion.MainWindow">
    <Grid>
        .....
      <uc:MainUserControl />
    </Grid>
</Window>

<UserControl x:Class="WpfApplicationUcBindingQuestion.MainUserControl">
<Grid>
.....
    <uc:SubUserControl1 x:Name="subUserControl1" />
</Grid>
</UserControl>

And in MainWindow I have object of class Info. Class Info consists of a few inner classes. One of them is, lets say, SubInfo. Both Info and SubInfo classes inherits from INotifyPropertyChanged.

And this is the code of them:

public class Info : INotifyPropertyChanged
{
    private SubInfo m_subInfo = new SubInfo();

    public Info()
    {
    }

    public SubInfo SubInfo 
    {
        get
        {
            return m_subInfo;
        }
        set
        {
            m_subInfo = value;
            OnPropertyChanged("SubInfo");
        }      
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    } 
}

public class SubInfo: INotifyPropertyChanged
{
    private string m_subString = "subStr";

    public SubInfo()
    {
    }

    public string SubString 
    {
        get
        {
            return m_subString;
        }
        set
        {
            m_subString = value;
            OnPropertyChanged("SubString");
        }      
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    } 
}

I want to set DataContext for MainUserControl to be object of class Info and for SubUserControl1 DataContext will be Info.SubInfo.

The following code describes this:

<UserControl x:Class="WpfApplicationUcBindingQuestion.SubUserControl1">
   <Grid>
      .....
    <TextBox Text="{Binding Path=SubString}"/> 
   </Grid>
</UserControl>

public MainUserControl()
{
        InitializeComponent();

        MainWindow mainWnd = (MainWindow)Application.Current.MainWindow;

        Info info = mainWnd.Info;
        this.DataContext = info;

        this.subUserControl1.DataContext = info.SubInfo;
}

When new subInfo arrived I update inner object subInfo inside info object: (This is function of MainWindow)

private void OnUpdateData()
{
    SubInfo arrivedSubInfo = new SubInfo();
    arrivedSubInfo.SubString = "newString";

    m_info.SubInfo = arrivedSubInfo;
}

I want to see that DataContext for subUserControl1 is also changed.

But it doesn't happened and TextBox inside SubUserControl1 is not updated and doesn't show "newString".

(Note: If I write inside OnUpdateData() function the following:

m_info.SubInfo.SubString = arrivedSubInfo.SubString;

(copy field-field and not whole object) it works, but I dont 'want copy 50 field...)

Where I'm wrong? Your help will be really appreciated.

Upvotes: 0

Views: 561

Answers (1)

Damascus
Damascus

Reputation: 6651

Your problem is the following:

In your constructor, when you do that:

    this.DataContext = info;

    this.subUserControl1.DataContext = info.SubInfo;

You will set the DataContext ONLY once. Which means it will never change unless you write subUserControl1.DataContext = someNewDataContext somewhere.

What you can do to solve this :

The "proper solution":

Use a binding. In your XAML, just write:

<uc:SubUserControl1 x:Name="subUserControl1" DataContext="{Binding
SubInfo, UpdateSourceTrigger=PropertyChanged}" />

This will work, assuming that your SubInfo property fires the OnPropertyChanged event when it is set.

The "ugly solution":

Explicitly set your UserControl's DataContext in code-behind when you need it. Again, I wouldn't advise that and you are better off applying the first solution!

Upvotes: 3

Related Questions