在运行时生成的属性(PropertyGrid.SelectedObject)

时间:2010-11-03 21:33:41

标签: c# reflection properties propertygrid

好的,这是一个艰难的。

简介:我的想法是将我编写的instanciated QueryBuilder类附加到PropertyGrid。 QueryBuilder类现在包含几个字段,这些字段是硬编码的,如下例所示。因此允许用户指定应以何种方式在查询中使用哪些字段(排序,分组等)。在用户为这些属性指定了所有设置后(通过代码或通过PropertyGrid GUI),QueryBuilder能够生成查询。一切都很好。伪代码:

class QueryBuilder {
  public QBField name {get; set;}
  public QBField prename {get; set;}
  public QBField zip {get; set;}
  // ...

  public void QueryBuilder() {
    name = new QBField();
    prename = new QBField();
    // ...
  }

  public getQuery() {
    // logic to build the query
  }
}

class QBField {
  public bool shown {get; set;}
  public bool sortby {get; set;}
  public bool groupby {get; set;}
}

挑战:现在我不想将每个字段硬编码为QueryBuilder类中的公共属性,而是想知道如何使用包含所有字段的List<string>来“填充”我的实例化具有这些属性的QueryBuilder。

所以这导致了三个问题:

  1. 这可以通过以某种方式覆盖QueryBuilder类的Type的GetProperties()来实现,如果是,那么它最好如何完成?

  2. 如何在运行时生成的QBField属性中迭代所有这些并生成它们?想法:PropertyDescriptors和Activators?

  3. 如何迭代所有这些属性来读取每个QBField对象的值?我遇到的问题是,当用反射读取QBField的属性并尝试getValue(obj,null)时,当然需要的第一个参数是一个对象,我不知道,因为我有很多这些QBField对象。也许把我所有的QBField都放到List<QBField>并迭代它?这会在这个例子中起作用吗?

  4. 我只是有点迷失,但我觉得我非常接近解决方案。因此,对于正确方向的任何帮助或指示都非常感激!

1 个答案:

答案 0 :(得分:5)

PropertyGrid可以通过TypeConverterICustomTypeDescriptor和/或TypeDescriptionProvider受到影响。其中,TypeConverter是最简单的,通过覆盖GetProperties(并将其标记为支持)。

在任何情况下,您还需要编写一个PropertyDescriptor实现,该实现知道如何获取字段和对象,并获取/设置值,即

public override void SetValue(object component, object value) {
    ((YourType)component)[fieldNameSetInConstructor] = value;
}

这是一个基本的属性包,它将所有内容公开为string;显然,当您扩展它(不同的属性类型,更改通知等)时,它会变得更加复杂。另请注意,此TypeConverter方法仅适用于PropertyGrid;对于DataGridView等,您需要ICustomTypeDescriptorTypeDescriptionProvider。对于收藏,您需要ITypedList。对于特定场景,边缘周围还有大约20个其他接口。但是你得到了重点; p关键是我们的PropertyDescriptor充当你的实际模型(在我的情况下是字典)和你公开的模型{{1 (每个键的假属性)。

TypeDescriptor