如何在导出List 的类中数据绑定到与列表项无关的属性

以前,我有一个包含内部System.Collections.Generic.List的类(其中Item是我创建的类)。 包装器类提供了几个集合级属性,这些属性提供了列表中项目的总计,平均值和其他计算。 我正在围绕这个包装的List和我的类周围的另一个BindingSource创建一个BindingSource ,并且能够通过第一个BindingSource获取包装列表中的Items以及使用第二个包装类的集合级属性。

一个简化的例子如下:

 public class OldClass() { private List _Items; public OldClass() { _Items = new List(); } public List Items { get { return _Items; } } // collection-level properties public float AverageValue { get { return Average() } } public float TotalValue { get { return Total() } } // ... other properties like this } 

使用以这种方式创建的绑定源:

 _itemsBindingSource = new BindingSource(oldClass.Items); _summaryBindingSource = new BindingSource(oldClass); 

最近,我尝试将此类更改为从System.Collections.Generic.List派生而不是保留包装的List成员。 我希望摆脱额外的包装层,只使用一个BindingSource而不是两个。 但是,现在我发现在进行数据绑定时,我无法获取适用于列表中所有项目的属性(例如AverageValue )。 只有列表项的属性可用。

我是否被迫回到使用Item s的包装List ? 或者有没有办法可以获得存储我的新类的Item的属性以及适用于集合本身的属性?

系统将实现IList (或IListSource )的任何内容视为容器,而不是项目。 因此,您无法绑定到实现IList的任何IList 。 因此,如果您希望能够绑定到容器的属性,那么封装 (即您已经拥有的)是最好的方法。

但是,您应该注意到许多绑定支持源中的点符号 – 即绑定到“Items.SomeProperty”,或者设置辅助属性(通常是DataMember )以指定子列表。

这允许您拥有单个BindingSource ,并且具有绑定到层次结构中不同级别的不同控件 – 即,您可能具有绑定到AverageValueTextBox ,以及具有DataMember="Items"DataGridView (具有相同的DataSource )。

这里的问题是你想要将你的一个类用于两个完全不同的目的(就绑定而言)。

示例:“AverageValue”属性对每个项目没有意义,因为它是跨越所有项目的全局属性。

无论哪种方式,我猜你的_itemsBindingSource用于ComboBox或其他东西,并且你的_summaryBindingSource用于PropertyGrid(或类似的东西)。

可以做什么, 可能在你的情况下工作(我不能确定,因为我不知道你在做什么)是这样的:

1)让你的“OldClass”实现IEnumerable ……然后,只需返回列表中的枚举即可。 这将使您能够绑定到“oldClass”而不是“oldClass.Items”。

2)使“公共列表项”成为一个字段,而不是属性…或添加“可浏览(错误)”属性,以便它不会绑定到PropertyGrid(这是一个猜测,因为它不清楚你是什么’重新使用这些绑定)。

您是否考虑过创建扩展类(假设您使用的是C#3),而不是在List周围创建包装类

 public static class MyExtensions { public static float GetAverage(this List) { // implementation } public static float GetTotal(this List) { // implementation } } 

当然,你的属性成为方法调用( 也许C#4会解决这个问题 ),但你会完全消除包装器。