0

I implemented a model class and want to raise PropertyChanged events for all subproperty when the object is modified. But I found it 's not working. When I push the button, the label's text is't changed.Does i miss something?I got this from MSDN -"The PropertyChanged event can indicate all properties on the object have changed by using either null or String.Empty as the property name in the PropertyChangedEventArgs." the platform is .net framework 4.0 and VS2015

   public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        Model = new Model()
        {
            data = new User()
            {
                Name = "test"
            }
        };
        label1.DataBindings.Add("Text", Model.data, "Name", false, DataSourceUpdateMode.OnPropertyChanged);
    }
    private Model model;
    public Model Model
    {
        get
        {
            return this.model;
        }
        set
        {
            model = value;
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        User temp = new User()
        {
            Name = "test1"
        };
        Model.data = temp;
    }
}

public class NotifyPropertyChanged : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
    protected bool SetField<T>(ref T field, T value, string propertyName = null)
    {
        if (EqualityComparer<T>.Default.Equals(field, value)) return false;
        field = value;
        OnPropertyChanged(propertyName);
        OnPropertyChanged(null);
        return true;
    }
}
public class Model : NotifyPropertyChanged
{
    private User m_data;
    public User data
    {
        get { return m_data; }
        set
        {
            SetField(ref m_data, value,"data");
        }
    }
}
public class User : NotifyPropertyChanged
{
    private string name;
    public string Name
    {
        get { return this.name; }
        set
        {
            SetField(ref name, value, "Name");
        }
    }
    private string tel;
    public string Tel
    {
        get { return this.tel; }
        set
        {
            SetField(ref tel, value, "Tel");
        }
    }
}
William
  • 5
  • 2
  • 2
    You're binding to `Model.data` - that is, the specific instance of `data` at that time. This never changes. I'm not really familiar with how binding works in Winforms, but [this question](http://stackoverflow.com/questions/8894103/does-data-binding-support-nested-properties-in-windows-forms) may help. – Charles Mager Mar 29 '17 at 07:53
  • @CharlesMager thanks. It helps a lot – William Mar 31 '17 at 08:01

1 Answers1

0

Your problem is that your binding on Model.data, but later on, assign it a new value.
So the instance that is being monitored by the binding, is no more being used.

You've 2 options:

First one: don't create new User, just change it's Name:

private void button1_Click(object sender, EventArgs e)
{
    Model.data.Name = "test1";
}

Or, if you really need to support both case (creation and assigment), then you have to change the binding to the Model and take the text from data.Name:

label1.DataBindings.Add("Text", Model, "data.Name", false, 
                        DataSourceUpdateMode.OnPropertyChanged);

And the set part of the User Property in the Model to this:

set
{
    SetField(ref m_data, value, "data");
    this.data.PropertyChanged += (sender, args) => this.OnPropertyChanged("data");
}

So, this will create a PropertyChanged on the data, if data.Name has been changed, well if the data property itself has been set

Ofir Winegarten
  • 9,215
  • 2
  • 21
  • 27