我有一个对象,我已经使用C#WinForms(目标.NET 4.5.2)绑定到表单上的控件。我已经实现了INotifyPropertyChanged
,当我修改此对象的属性时,它会按预期更新Form的控件。但是,当我将此对象的实例更改为新实例时,即使我尝试修改特定属性,它也不会再更新控件。
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;
}
}
并在表格上
User currentUser = new User("Example Name");
lblName.DataBindings.Add("Text", currentUser, "Name");
正确更新。我可以使用currentUser.Name = "Blahblah";
更改名称,它可以正常工作。当我尝试拨打currentUser = new User("New Name");
时,无论我做什么,它都将不再更新。
据我所知,对象的特定实例是控件绑定的对象。我的主要目标是不必手动浏览较大对象的每个属性,并在每次想要更改实例时手动更改所有内容。
我的问题:有没有办法在不删除绑定到控件的情况下更改对象的实例?
答案 0 :(得分:2)
要获得所需的行为,您不应该像目前那样直接绑定到具体实例:
lblName.DataBindings.Add("Text", currentUser, "Name");
相反,你需要一些中间人。最简单的方法是使用BindingSource
组件来实现此目的。
在表单中添加BindingSource
字段:
private BindingSource dataSource;
然后初始化它并将控件绑定到它一次(通常以Load
事件形式):
dataSource = new BindingSource { DataSource = typeof(User) };
lblName.DataBindings.Add("Text", dataSource, "Name");
// ...
现在,只要您想要绑定到User
个实例,只需将其分配给DataSource
的{{1}}属性:
初始:
BindingSource
后:
dataSource.DataSource = new User("Example Name");
答案 1 :(得分:2)
伊万告诉你如何解决这个问题。在这个答案中,我将尝试向您展示问题是什么以及为什么这样做。
简短回答
您的标签绑定到的对象不是变量。变量就像指向对象的指针。因此,替换变量不会对标签用作数据源的对象产生任何影响。只是变量指向新对象。但是您的标签正在使用上一个对象。它有自己的指向前一个对象的指针。
请考虑以下事实来了解正在发生的事情:
User currentUser = new User("Example Name");
将对象分配给变量时,实际上变量指向对象。
lblName.DataBindings.Add("Text", currentUser, "Name");
currentUser.Name = "Blahblah";
您更改了Name
属性的值,自您实施INotifyPropertyChanged
后,控件会收到更改通知,并会刷新其Text
。
但主要陈述没有按预期发挥作用:
currentUser = new User("New Name");
在这里,您将currentUser
变量指向另一个对象。它与它指向的前一个对象没有任何关系。它只是指向另一个对象。
您添加到标签的Binding
仍然使用上一个对象。
因此没有任何通知是正常的,因为标签使用的对象没有改变。
BindingSource如何解决问题?
BindingSource
在您为ListChanged
分配新对象时引发DataSource
事件,并使BindingObject
从DataSource
获取新值并刷新Text
{1}}财产。你可以看一下这篇文章:How to make a binding source aware of changes in its data source?