【问题标题】:Data binding stops working after the bound list been replaced绑定列表被替换后数据绑定停止工作
【发布时间】:2010-10-04 23:47:30
【问题描述】:

这是一个 C# 中的数据绑定问题。

我有一个简单的 Person 类:

public class Person {
    public string Name {get; set;}
    public string Level {get; set;}
}

我有一个 Group 类,它包含一个 Persons 属性作为 Person 实例的 BindingList:

public class Group {
    private BindingList<Person> persons_;
    public BindingList<Person> Persons {
            get { return persons_; }
            set { persons_ = value; }
    }
}

最后,我使用 BindingSource 将组实例连接到 DataGridView:

// Instantiate a Group instance.
Group p = new Group();
p.Persons = new BindingList<Person> {
    new Person {Name = "n1", Level = "l1"},
    new Person {Name = "n2", Level = "l2"},
    new Person {Name = "n3", Level = "l3"}
};

BindingSource bs = new BindingSource();
bs.DataSource = p;
bs.DataMember = "Persons";
DataGridView dgv = new DataGridView();
dgv.DataSource = bs;

在上面的代码之后,DataGridView 会显示三个 Person 实例。一切正常。然后我有一个按钮,当单击该按钮时,我创建另一个 Person BindingList 并用它来替换 p.Persons:

p.Persons = new BindingList<Person> {
    new Person {Name = "n10", Level = "l10"},
    new Person {Name = "n11", Level = "l11"},
    new Person {Name = "n12", Level = "l12"}
};

在上面的代码之后,数据绑定停止工作。从 BindingSource 或 DataGridView 添加 ResetBindings() 调用并不能解决数据绑定的中断问题。

由于我的 BindingSource 绑定到 Group 类的 Persons 属性,我认为 Persons 属性的更改不应该破坏数据绑定,但实际上确实如此。但这是我们通常在将字符串属性绑定到标签或文本框时所做的。我们只需为属性分配一个新的字符串实例,标签或文本框将正确更新自身。为什么这不适用于实例集合?实现相同行为的正确代码是什么?非常感谢。

【问题讨论】:

    标签: c# data-binding


    【解决方案1】:

    您的数据模型非常错误:Collection properties should be readonly。

    相反,您应该删除 Persons 设置器,然后清除列表并重复调用 Add。
    如果你愿意,你甚至可以创建一个扩展方法

    public static void  ReplaceWith<T>(this IList<T> list, params T[] newItems)
    

    【讨论】:

    • 您的建议是正确的。但是如果 BindingList 有很多项目,当我在 setter 中更新它时,我清除项目并一个一个添加项目,DataGridView UI 会在每次添加项目时自行更新,这会不会产生太多额外的工作?在添加项目开始时告诉 BindingSource 暂停并在之后恢复会很好。但是在 Group.Persons 属性的 setter 或 Group 内部,不知道 BindingSource。
    • @Steve:您可以创建自己的类,该类继承 BindingList&lt;T&gt; 并包含修改基础列表的 ReplaceWith 方法(因此不会引发任何事件),然后引发 Reset。
    • @Steve:SuspendBinding() 和 ResumeBinding() 方法可能会对您有所帮助。
    • @Anna Lear:SuspendBinding() 和 ResumeBinding() 是 BindingSource 的方法,在 Group 类中无法访问。我发现 BindingList 的 RaiseListChangedEvents 属性可以做我想做的事情。
    • 你是对的;我忘记了那个属性。您可以在扩展方法中设置它。
    【解决方案2】:

    这是因为Persons 属性在更改时不会触发通知。 Group 类应该实现INotifyPropertyChanged,Persons 属性的设置器应该引发PropertyChanged 事件。

    【讨论】:

    • 另一种方法是在 Persons 属性上调用 Clear() 并重新填充它,而不是创建新的 BindingList。
    • INotifyPropertyChanged 的​​实现没有帮助。实际上 ResetBinding() 的调用会做类似的事情。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-11
    • 2016-07-16
    • 2015-10-04
    • 1970-01-01
    • 2017-03-15
    • 1970-01-01
    • 2020-02-01
    相关资源
    最近更新 更多