C# 网格数据源多态性 [英] C# grid DataSource polymorphism
问题描述
我有一个网格,我将 DataSource
设置为 List
.我想要的是将列表绑定到基础类型,并显示这些属性,而不是 IListItem
中定义的属性.所以:
I have a grid, and I'm setting the DataSource
to a List<IListItem>
. What I want is to have the list bind to the underlying type, and disply those properties, rather than the properties defined in IListItem
. So:
public interface IListItem
{
string Id;
string Name;
}
public class User : IListItem
{
string Id { get; set; };
string Name { get; set; };
string UserSpecificField { get; set; };
}
public class Location : IListItem
{
string Id { get; set; };
string Name { get; set; };
string LocationSpecificField { get; set; };
}
如何绑定到网格,以便如果我的 List
包含用户,我将看到用户特定的字段?请注意,我想绑定到 Datagrid 的任何给定列表都将由单个基础类型组成.
How do I bind to a grid so that if my List<IListItem>
contains users I will see the user-specific field? Note that any given list I want to bind to the Datagrid will be comprised of a single underlying type.
推荐答案
数据绑定到列表遵循以下策略:
Data-binding to lists follows the following strategy:
- 数据源是否实现了
IListSource
?如果是这样,使用GetList()
的结果转到 2 - 数据源是否实现了
IList
?如果不是,则抛出错误;预期列表 - 数据源是否实现了
ITypedList
?如果是这样,请将其用于元数据(退出) - 数据源是否有非对象索引器,
public Foo this[int index]
(对于某些Foo
)?如果是这样,请使用typeof(Foo)
作为元数据 - 列表中有什么吗?如果是,则使用第一项 (
list[0]
) 作为元数据 - 没有可用的元数据
- does the data-source implement
IListSource
? if so, goto 2 with the result ofGetList()
- does the data-source implement
IList
? if not, throw an error; list expected - does the data-source implement
ITypedList
? if so use this for metadata (exit) - does the data-source have a non-object indexer,
public Foo this[int index]
(for someFoo
)? if so, usetypeof(Foo)
for metadata - is there anything in the list? if so, use the first item (
list[0]
) for metadata - no metadata available
List
属于上面的4",因为它有一个 IListItem
类型的索引器 - 所以它将通过 TypeDescriptor 获取元数据.GetProperties(typeof(IListItem))
.
List<IListItem>
falls into "4" above, since it has a typed indexer of type IListItem
- and so it will get the metadata via TypeDescriptor.GetProperties(typeof(IListItem))
.
现在,您有三个选择:
- 编写一个
TypeDescriptionProvider
返回IListItem
的属性 - 我不确定这是否可行,因为你不可能知道具体的类型是什么IListItem
代码>IListItem - 使用正确类型的列表(
List
等) - 简单地作为使用非对象索引器获取IList
的简单方法 - 编写一个
ITypedList
包装器(大量工作) - 使用类似
ArrayList
的东西(即没有公共的非对象索引器) - 非常hacky!
- write a
TypeDescriptionProvider
that returns the properties forIListItem
- I'm not sure this is feasible since you can't possibly know what the concrete type is given justIListItem
- use the correctly typed list (
List<User>
etc) - simply as a simple way of getting anIList
with a non-object indexer - write an
ITypedList
wrapper (lots of work) - use something like
ArrayList
(i.e. no public non-object indexer) - very hacky!
我的偏好是使用正确类型的 List<>
...这里有一个 AutoCast
方法,它可以为您执行此操作而无需知道类型(带有示例用法);
My preference is for using the correct type of List<>
... here's an AutoCast
method that does this for you without having to know the types (with sample usage);
请注意,这只适用于同类数据(即所有对象都相同),并且需要列表中至少有一个对象来推断类型...
Note that this only works for homogeneous data (i.e. all the objects are the same), and it requires at least one object in the list to infer the type...
// infers the correct list type from the contents
static IList AutoCast(this IList list) {
if (list == null) throw new ArgumentNullException("list");
if (list.Count == 0) throw new InvalidOperationException(
"Cannot AutoCast an empty list");
Type type = list[0].GetType();
IList result = (IList) Activator.CreateInstance(typeof(List<>)
.MakeGenericType(type), list.Count);
foreach (object obj in list) result.Add(obj);
return result;
}
// usage
[STAThread]
static void Main() {
Application.EnableVisualStyles();
List<IListItem> data = new List<IListItem> {
new User { Id = "1", Name = "abc", UserSpecificField = "def"},
new User { Id = "2", Name = "ghi", UserSpecificField = "jkl"},
};
ShowData(data, "Before change - no UserSpecifiedField");
ShowData(data.AutoCast(), "After change - has UserSpecifiedField");
}
static void ShowData(object dataSource, string caption) {
Application.Run(new Form {
Text = caption,
Controls = {
new DataGridView {
Dock = DockStyle.Fill,
DataSource = dataSource,
AllowUserToAddRows = false,
AllowUserToDeleteRows = false
}
}
});
}
这篇关于C# 网格数据源多态性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!