5

这个问题(连同它的答案)解释了为什么您不能轻松地将 DataGridView 绑定到接口类型并获取从基本接口继承的属性的列。

建议的解决方案是实现自定义 TypeConverter。我的尝试如下。但是,创建绑定到 ICamel 的 DataSource 和 DataGridView 仍然只会产生一列(Humps)。我不认为.NET 正在使用我的转换器来决定它可以为 ICamel 看到哪些属性。我究竟做错了什么?

[TypeConverter(typeof(MyConverter))]
public interface IAnimal
{
    string Name { get; set; }
    int Legs { get; set; }
}

[TypeConverter(typeof(MyConverter))]
public interface ICamel : IAnimal
{
    int Humps { get; set; }
}

public class MyConverter : TypeConverter
{
    public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
    {
        if(value is Type && (Type)value == typeof(ICamel))
        {
            List<PropertyDescriptor> propertyDescriptors = new List<PropertyDescriptor>();
            foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(typeof(ICamel)))
            {
                propertyDescriptors.Add(pd);
            }
            foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(typeof(IAnimal)))
            {
                propertyDescriptors.Add(pd);
            }
            return new PropertyDescriptorCollection(propertyDescriptors.ToArray());
        }
        return base.GetProperties(context, value, attributes);
    }

    public override bool GetPropertiesSupported(ITypeDescriptorContext context)
    {
        return true;
    }
}
4

3 回答 3

3

DataGridView不使用TypeConverterPropertyGrid使用TypeConverter.

如果它与类似的列表控件有关DataGridView,那么另一个答案是错误的。

要在列表中提供自定义属性,您需要以下之一:

  • ITypedList在数据源上
  • TypeDescriptionProvider关于类型

两者都不是微不足道的。

于 2009-06-26T11:24:08.473 回答
1

我的解决方法发生在 dgv 的绑定中。我确实需要基本接口和继承接口保持在相同的结构中,只是因为我在最终的具体类中做了其他事情,而不仅仅是在 DataGridView 上显示数据。因此,例如:

interface IGenericPerson
{
    int ID { get; set; }
    string Name { get; set; }
}

interface IOperator : IGenericPerson
{
    bool IsAdmin { get; set; }
}

具体类:

class Operator : IOperator
{
    public Operator(){}

    public Operator(int id, string name, bool isAdmin)
    {
        this.ID = id;
        this.Name = name;
        thsi.IsAdmin = isAdmin;
    }

    public int ID { get; set; }
    public string name { get; set; }
    public bool IsAdmin { get; set; }
}

在网关类中:

public IList<IOperator> GetOperators()
{
    IList<IOperator> list = new List<IOperator>();

    list.add(new Operator(112, "Mark Twain", false);
    list.add(new Operator(112, "Charles Manson", false);
    list.add(new Operator(112, "Richard Nixon", true);

    return list;
}

现在,如果我尝试像这样绑定 datagridView:

Gateway gt = new Gateway();
dgv.DataSource = gt.GetOperators();

我从 IOperator 接口获得了一个带有唯一 bool IsAdmin 列的 DataGridView,而不是 ID,也不是来自其基本接口的 Name 属性。

但如果我这样做:

Gateway gt = new Gateway();

IList<IOperator> list = gt.GetOperators();

IList<Operator> ds = new List<Operator>();

foreach(IOperator op in list)
    ds.add((Operator)op);

dgv.DataSource = ds;

一切都以正确的方式工作。

通过这种方式,我不需要更改 intarfaces 链的结构,对其他用途很有用,并且只显示数据,我只需插入上面的代码片段。

于 2011-07-02T11:07:49.370 回答
0

我的建议是创建一个“重新实现”您想要的属性的接口:

假设您有两个接口:

public interface IHasName1
{
    String Name1 { get; set; }
}

public interface IHasName2 : IHasName1
{
    String Name2 { get; set; }
}

还有一个实现 IHasName2 的类:

public class HasTwoNames : IHasName2
{
    #region IHasName1 Member
    public string Name1 { get; set; }
    #endregion

    #region IHasName2 Member
    public string Name2 {get; set; }
    #endregion
}

现在,顺便说一句,谢谢,如果您有一个包含具体类型 HasTwoNames 的对象的列表,并且将该列表绑定到 dgv,它只会显示 IHasName2 的成员 (Name2)。

“解决方法”是创建一个新接口“IHasEverything”,该接口继承自 IHasName2,因此继承自 IHasName1,并重新实现绑定中所需的属性(您可以使用 new 语句执行此操作

public interface IHasEverything : IHasName2
{
    new String Name1 { get; set; }
    new String Name2 { get; set; }
}

现在你的具体类“HasTwoNames”也需要实现 IHasEverything:

public class HasTwoNames : IHasName2, IHasEverything
{
    ...
}

您可以将此列表绑定到数据网格视图:

    public List<IHasEverything> elements = new List<IHasEverything> {
        new HasTwoNames { Name1 = "Name1", Name2 = "Name2"},
        new HasTwoNames { Name1 = "Name3", Name2 = "Name4"},
    };

我知道这只是一种解决方法,只有在您可以修改实现类的情况下才有可能。但它有效。(如果您从 IHasName2 中删除一个属性,代码仍将编译,但您会收到 IHasEverything 不需要 new 关键字的警告。

于 2009-06-26T13:13:28.347 回答