Data binding does not work when I assign an instance of a new object to a related variable

I have an object that I attached to a control using C # WinForms (target .NET 4.5.2). I implemented INotifyPropertyChanged , and when I change the Property of this object, it, as expected, updates the form control. However, when I change an instance of an object to a new instance, it will no longer update the control, even if I try to change a specific property.

 class User : INotifyPropertyChanged { string _name = ""; public string Name { get { return _name; } set { _name = value; OnPropertyChanged("Name"); } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string property) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); } public User() { } public User(string name) { Name = name; } public User(User otherUser) { Name = otherUser.Name; } } 

and in form I

 User currentUser = new User("Example Name"); lblName.DataBindings.Add("Text", currentUser, "Name"); 

which is updated properly. I can change the name using currentUser.Name = "Blahblah"; and it works great. When I try to call currentUser = new User("New Name"); , it will no longer update, no matter what I do.

I understand that a particular instance of an object is what the controls are attached to. My main goal is not to manually go through each property of larger objects and manually change everything every time I want to change instances.

My question is: is there a way to change instances of an object without unlinking the control?

+5
source share
2 answers

To get the desired behavior, you should not directly contact a specific instance, as it is now:

 lblName.DataBindings.Add("Text", currentUser, "Name"); 

Instead, you need some kind of intermediary. The easiest way is to use the BindingSource component for this purpose.

Add the BindingSource field to the form:

 private BindingSource dataSource; 

Then initialize it and bind the controls to it once (usually in the form of a Load event):

 dataSource = new BindingSource { DataSource = typeof(User) }; lblName.DataBindings.Add("Text", dataSource, "Name"); // ... 

Now that you want to bind to the User instance, you simply assign it to the DataSource BindingSource property:

Initial:

 dataSource.DataSource = new User("Example Name"); 

later:

 dataSource.DataSource = new User("New Name"); 
+2
source

Ivan showed you how to solve the problem. Here in this answer, I will try to show you what the problem is and why it works this way.

Short answer

Your label is bound to an object, not a variable. The variable is the same as a pointer to an object. Thus, replacing a variable does not affect the object that your label uses as a data source. Only a variable points to a new object. But your shortcut uses the previous object. It has its own pointer to the previous object.

Review these facts to find out what happens:

  • User currentUser = new User("Example Name");

    When you assign an object to a variable, the variable actually points to the object.

  1. lblName.DataBindings.Add("Text", currentUser, "Name");
    You have bound data to an object. The control will be bound to the object, not to the variable.
    1. currentUser.Name = "Blahblah";

      You have changed the value of the Name property, and since you have implemented INotifyPropertyChanged , the control will be notified of the changes and will update it Text .

But the main operator, which did not work as you expected :

  1. currentUser = new User("New Name");

    Here you pointed the point currentUser variable to another object. It has nothing to do with the previous object that it was pointing to. It just points to another object.

    Binding you added to the label still uses the previous object.

    So, it’s normal to not have any notice, because the object used by the shortcut has not changed.

How did the BindingSource problem solve the problem?

The BindingSource event ListChanged event when you assign a new object to its DataSource , and it returns BindingObject new value from the DataSource and updates the Text property. You can see the message: How to make a binding source aware of changes in its data source?

+2
source

Source: https://habr.com/ru/post/1257611/


All Articles