2016-10-02 48 views
5

我有一个对象绑定到使用C#WinForms(定位.NET 4.5.2)的窗体上的控件。我已经实现了INotifyPropertyChanged,并且当我修改此对象的Property时,它按照预期更新了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");时,无论我做什么,它都不会再更新。

我的理解是,对象的特定实例是控件绑定的内容。我的主要目标是不必手动遍历更大对象的每个属性,并在每次更改实例时手动更改所有内容。

我的问题:有没有一种方法来更改对象的实例,而无需去除绑定到控件?

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

相反,你需要一些中介:

回答

2

为了获得所需的行为,你不应该直接像你目前做绑定到具体实例。最简单的就是使用BindingSource组件。

一个BindingSource字段添加到窗体:

private BindingSource dataSource; 

对其进行初始化和控件绑定到它一个时间(通常在形式上Load事件):

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

现在,只要你想绑定到User实例,只需将其分配给BindingSourceDataSource属性:

初始:

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

后:

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

这工作完美。谢谢! – pfthroaway

2

伊万展示了如何解决这个问题。在这个答案中,我会试着告诉你什么是问题,以及它为什么这样工作。

简短的回答

你的标签绑定到一个对象不变量。该变量就像一个指向该对象的指针。因此,替换该变量对您的标签用作数据源的对象没有任何影响。只是变量指向新对象。但是你的标签正在使用之前的对象。它有自己的指向前一个对象的指针。

考虑到这些事实,就知道发生了什么:

  1. 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提高,当你分配一个新的对象到其DataSourceListChanged事件,它使BindingObjectDataSource获取新的价值,并刷新Text财产。你可以看看这篇文章:How to make a binding source aware of changes in its data source?

    +0

    这是非常翔实的。谢谢。 – pfthroaway

    +0

    不客气:) –

    +0

    好的解释! –