当我将新对象实例分配给绑定变量

时间:2016-10-02 12:58:23

标签: c# .net winforms data-binding

我有一个对象,我已经使用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");时,无论我做什么,它都将不再更新。

据我所知,对象的特定实例是控件绑定的对象。我的主要目标是不必手动浏览较大对象的每个属性,并在每次想要更改实例时手动更改所有内容。

我的问题:有没有办法在不删除绑定到控件的情况下更改对象的实例?

2 个答案:

答案 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)

伊万告诉你如何解决这个问题。在这个答案中,我将尝试向您展示问题是什么以及为什么这样做。

简短回答

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

请考虑以下事实来了解正在发生的事情:

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

    将对象分配给变量时,实际上变量指向对象。

    1. lblName.DataBindings.Add("Text", currentUser, "Name");
      您对该对象执行了数据绑定。控件将绑定到对象而不是变量。
      1. currentUser.Name = "Blahblah";

        您更改了Name属性的值,自您实施INotifyPropertyChanged后,控件会收到更改通知,并会刷新其Text

      2. 但主要陈述没有按预期发挥作用

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

          在这里,您将currentUser变量指向另一个对象。它与它指向的前一个对象没有任何关系。它只是指向另一个对象。

          您添加到标签的Binding仍然使用上一个对象。

          因此没有任何通知是正常的,因为标签使用的对象没有改变。

        2. BindingSource如何解决问题?

          BindingSource在您为ListChanged分配新对象时引发DataSource事件,并使BindingObjectDataSource获取新值并刷新Text {1}}财产。你可以看一下这篇文章:How to make a binding source aware of changes in its data source?