运行时生成的属性 (PropertyGrid.SelectedObject)
好吧,这是一个艰难的问题。
简介:我的想法是将我编写的实例化 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;}
}
挑战:现在,我想知道如何使用包含所有字段的 List
,而不是将每个字段硬编码为 QueryBuilder 类中的公共属性使用这些属性“填充”我的实例化 QueryBuilder。
因此,这导致了三个问题:
这是否可以通过某种方式重写 QueryBuilder 类的 Type 的 GetProperties() 来完成,如果可以,最好如何完成?
然后我如何迭代所有这些在运行时生成的 QBField 属性并实例化它们?想法:PropertyDescriptors 和 Activators?
如何迭代所有这些属性来读取每个 QBField 对象的值?我遇到的问题是,当使用反射读取 QBField 的属性并尝试 getValue(obj, null) 时,当然需要的第一个参数是一个对象,我不知道这个对象,因为我有很多这样的 QBField 对象。也许将我所有的 QBField 放入
List
并迭代它?在这个例子中这可行吗?
我只是有点迷失,但我觉得我已经非常接近解决方案了。因此,我们非常感谢任何帮助或正确方向的指示!
Ok, this is a tough one.
Introduction: My idea is to attach an instanciated QueryBuilder class which I wrote, to a PropertyGrid. The QueryBuilder class now contains a couple of fields, which are hardcoded like in the example below. Thus allowing a user to specify, which fields should be used in a query in what way (sorted, grouped, and so on). After the user having specified all the settings to these properties (by code or via the PropertyGrid GUI), the QueryBuilder is able to produce a query. Everything is working fine like that. Pseudo code:
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;}
}
Challenge: Now instead of hardcoding each field as public properties in the QueryBuilder class, I was wondering how I could use i.e. a List<string>
containing all my fields to "populate" my instanciated QueryBuilder with these properties.
So this leads to three questions:
Could this be accomplished by somehow overriding GetProperties() of the Type of the QueryBuilder class, and if yes, how is it best done?
How can I then iterate through all of these at runtime generated QBField properties and instanciate them? Idea: PropertyDescriptors and Activators?
How can I iterate through all of these properties to read the values of each QBField object? The problem I ran in was, that when reading the Properties of QBField with reflection and trying getValue(obj, null), of course the first parameter needed is an object, which I do not know since I have lots of these QBField objects. Perhaps putting all my QBFields into a
List<QBField>
and iterating through it? Would that work in this example?
I'm just a bit lost but I feel that I'm very close to the solution. Therefore any help or just pointers in the right direction are most greatly appreciated!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
PropertyGrid
可以通过TypeConverter
、ICustomTypeDescriptor
和/或TypeDescriptionProvider
进行影响。其中,TypeConverter
是最简单的,通过重写GetProperties
(并将其标记为支持)。无论如何,您还需要编写一个
PropertyDescriptor
实现,它知道如何获取字段和对象,并获取/设置值,即这是一个基本属性将所有内容公开为字符串的包;显然,当你扩展这个(不同的属性类型、更改通知等)时,它很快就会变得更加复杂。另请注意,此
TypeConverter
方法仅适用于PropertyGrid
;对于DataGridView
等,您需要ICustomTypeDescriptor
或TypeDescriptionProvider
。对于集合,您需要ITypedList
。边缘还有大约 20 个其他接口,用于特定场景。但你明白了;p 关键是我们的PropertyDescriptor
充当您的实际模型(在我的例子中是字典)和您公开的模型之间的转换TypeDescriptor
(每个键的假属性)。PropertyGrid
can be influenced viaTypeConverter
,ICustomTypeDescriptor
and/orTypeDescriptionProvider
. Of these,TypeConverter
is the simplest, by overridingGetProperties
(and mark it as supported).In any event, you will also need to write a
PropertyDescriptor
implementation that knows how to take a field and an object, and get/set the value, i.e.Here's a basic property bag that exposes everything as
string
; obviously as you extend this (different property types, change-notification, etc) it gets more complex very quickly. Note also that thisTypeConverter
approach only works forPropertyGrid
; forDataGridView
etc you'll need eitherICustomTypeDescriptor
orTypeDescriptionProvider
. For collections you'll needITypedList
. And there are about 20 other interfaces around the edges for specific scenarios. But you get the point ;p The key thing is that ourPropertyDescriptor
acts as the translation between your actual model (the dictionary in my case), and the model you expose toTypeDescriptor
(the fake properties per key).