C# 网格数据源多态性 [英] C# grid DataSource polymorphism

查看:14
本文介绍了C# 网格数据源多态性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个网格,我将 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:

  1. 数据源是否实现了IListSource?如果是这样,使用 GetList()
  2. 的结果转到 2
  3. 数据源是否实现了IList?如果不是,则抛出错误;预期列表
  4. 数据源是否实现了ITypedList?如果是这样,请将其用于元数据(退出)
  5. 数据源是否有非对象索引器,public Foo this[int index](对于某些Foo)?如果是这样,请使用 typeof(Foo) 作为元数据
  6. 列表中有什么吗?如果是,则使用第一项 (list[0]) 作为元数据
  7. 没有可用的元数据
  1. does the data-source implement IListSource? if so, goto 2 with the result of GetList()
  2. does the data-source implement IList? if not, throw an error; list expected
  3. does the data-source implement ITypedList? if so use this for metadata (exit)
  4. does the data-source have a non-object indexer, public Foo this[int index] (for some Foo)? if so, use typeof(Foo) for metadata
  5. is there anything in the list? if so, use the first item (list[0]) for metadata
  6. 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 for IListItem - I'm not sure this is feasible since you can't possibly know what the concrete type is given just IListItem
  • use the correctly typed list (List<User> etc) - simply as a simple way of getting an IList 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆