繁体   English   中英

BindingList 与 List - WinForms 数据绑定

[英]BindingList vs List - WinForms Data Binding

为了让 WinForms 中的数据绑定(例如到 DataGridView)像您希望的那样工作并在集合更改时添加/删除行,您必须使用 BindingList(或 DataTable)而不是通用列表。 问题是,几乎没有人的第一直觉是在他们的库中使用 BindingList 而不是 List 进行编码。

BindingList 实现了两个 List 没有的事件,它们必须是数据绑定操作的不同之处(也是抑制第二个事件的属性):

AddingNew
ListChanged
RaiseListChangedEvents

同样,DataTable 有两个事件可能会启用类似的功能:

RowDeleted
TableNewRow

编辑:正如有用的 SO 社区在此处和另一篇文章中指出的那样,可以通过调用正确的 BindingList 构造函数来转换 List(也许更准确地封装?):

BindingList<MyType> MyBL = new BindingList<MyType>();
MyList.ForEach(x => MyBL.Add(x));

我的情况有点复杂,如下面的代码所示。 编辑添加了必须存在于真实库中的 INotifyPropertyChanged 内容。

public class RealString : INotifyPropertyChanged
{
  private int _KnotCount = 0;
  private List<KnotSpace> _KnotSpacings = new List<KnotSpace>();

  public RealString()
  {
    KnotSpacings.Add(new KnotSpace());
  }

  public int KnotCount
  {
    get { return _KnotCount; }

    set
    {
      int requiredSpacings = 0;

      _KnotCount = value;
      // Always one more space than knots
      requiredSpacings = _KnotCount + 1;

      if (requiredSpacings < KnotSpacings.Count)
      {
        while (requiredSpacings < KnotSpacings.Count)
        {
          KnotSpacings.Add(new KnotSpace());
        }
      }
      else if (requiredSpacings > KnotSpacings.Count)
      {
        while (requiredSpacings > KnotSpacings.Count)
        {
          KnotSpacings.Remove(KnotSpacings.Last());
        }
      }
      this.OnPropertyChanged(this, "KnotCount");
    }

  }

  public List<KnotSpace> KnotSpacings { get => _KnotSpacings; }

  public event PropertyChangedEventHandler PropertyChanged;

  protected virtual void OnPropertyChanged(object sender, string PropertyName)
  {
    if (this.PropertyChanged == null) return;
    this.PropertyChanged(sender, new PropertyChangedEventArgs(PropertyName));
  }

}

public class KnotSpace
{
  private double _Spacing = 10;

  public double Spacing { get => _Spacing; set => _Spacing = value; }

}

列表中的事物显示在 UI 中,列表中事物的属性在 UI 中进行修改,但 UI 不会直接从列表中添加/删除事物,除非更改 KnotCount 属性。 当通过更改 KnotCount 属性更新 KnotSpacings 时,将 KnotSpacings 属性包装在 BindingList 中不会导致 BindingList 更新。

编辑好的,更多说明......

BindingList BL = new BindingList<KnotSpace>(MyRealString.KnotSpacings);

DataGridView1.AutoGenerateColumns = true;
DataGridView1.DataSource = BL;
NumericUpDown1.DataBindings.Add("Value", MyRealString, "KnotCount", false, DataSourceUpdateMode.OnPropertyChanged);

与 Windows 控件相比,BindingList 在跟踪基础 List 属性 (KnotSpacings) 的更改方面没有更多成功。 因此,将控件绑定到 BindingList 的数据并没有太大的作用。 如果 UI 从 BindingList 添加/删除项目,则 BindingList 效果很好,因为它在底层 List 中执行相同的操作。 但随后我需要在我的 UI 中复制库的添加/删除操作和逻辑,这是等待中的重大变化。

编辑对我的原始帖子所做的主要更改,试图:(1)澄清问题。 (2) 将其区分为不是重复问题(尽管几个问题之一是重复问题)。 (3) 承认如果我删除帖子可能会失去其他人的有益努力。

首先,有一种更好的方法可以将List<T>传递给BindingList<T> BindingList<T>有一个接受List<T>的构造函数,它将List的元素复制到BindingList ,如下所示:

List<int> myList = new List<int>();
BindingList<int> myBindingList = new BindingList<int>(myList);

但这不是你的问题,真的。 简单地回答您的问题 -正确, List<T>不是 WinForms 中双向绑定的好选择 由于List<T>没有任何事件通知添加的元素,因此您实际上只能保证单向绑定 - 数据输入可能有效,但在尝试刷新时,例如添加到List项目时,事情会崩溃。

也就是说,您提到这些库正在修改您在修改期间有权访问的List<T> 我认为一个好的库会使用接口模式来使用、修改和传递集合。 尽管List<T>BindingList<T>是非常不同的类,但它们都实现了IList<T>ICollection<T>IEnumerable<T> 因此,任何接受这些接口作为参数的函数都可以接受List<T>BindingList<T> (例如: public void DoSomethingWithCollection(IEnumerable<int> collection)可以接受List<int> , BindingList<int> ,或任何其他实现IEnumerable<int>集合)。 Interface 模式是 C# 生命周期中的一个众所周知的标准,尽管没有人的第一直觉是在List<T>上使用BindingList<T> List<T> ,但他们的第一直觉绝对应该是使用IEnumerable<T> (或IList<T>ICollection<T> )在List<T>

在可能的情况下,绑定将您的List传递给BindingList的构造函数会更好,然后永远不要再次使用List - 相反,使用BindingListAddRemove方法来管理它的内部集合。

如果您使用接受IList<T>实例的BindingList<T>构造函数,则该实例用于支持BindingList<T> ,并且IList<T>中的更改反映在BindingList

然而,这并不是故事的结局。 WinForms 数据绑定的结构方式是,您离简单的、单一属性的 2 向绑定越远,您需要涵盖的内容就越多。

例如, INotifyPropertyChanged接口由用作数据源的类实现,以通知子属性(如KnotCount属性)的更改。

对于更复杂的场景,我们不会使用BindingList<T> ,而是从它派生一个类并覆盖一个或多个数据绑定机制。 BindingSource类也是如此。

数据绑定机制背后有很多样板,但几乎每个部分都可以派生以自定义行为。 绘制数据绑定中使用的类和接口的对象图有时很有用(大量阅读相关文档),以便对整个过程有一个很好的心理概述。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM