据我所知,属性网格被赋予一个对象,可以通过使用反射提取其属性来操作它。
我的问题是我有一组在运行时确定的参数,因此我不能静态地组合一个具有属性的类来表示这个集合。
我有两个想法来解决这个问题,但两者都很复杂,可能会花费很多时间,事实上我会说它们在我的时间限制下不实用。一种是使用Reflection Emit来动态定义一个类,另一种是动态构建一个C#源文件,然后使用CodeDom进行编译。
属性网格是否可以以不同的方式运行(除了使用反射提取对象的属性),这可以解决我的问题?
如果你不知道任何其他可以为我做这项工作的控件吗?
我想说,我从一开始就进入属性网格的原因是它能够为常见类型提供真正优秀的数据检索UI。对于颜色,您可以自动获取调色板,对于dataTime,您自动拥有一个漂亮的日历。如果可能的话,我想自动获取这些东西。
答案 0 :(得分:5)
是的,使用PropertyGrid
,TypeConverter
或ICustomTypeDescriptor
中的任何一个,TypeDescriptionProvider
可以显示其他而不仅仅是编译时属性提供运行时伪属性。你能举例说明你的参数是什么样的吗?我应该能够提供一个例子......
这是一个基于earlier reply(相关但不同)的基本示例(一切都是string
等):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
class PropertyBagPropertyDescriptor : PropertyDescriptor {
public PropertyBagPropertyDescriptor(string name) : base(name, null) { }
public override object GetValue(object component) {
return ((PropertyBag)component)[Name];
}
public override void SetValue(object component, object value) {
((PropertyBag)component)[Name] = (string)value;
}
public override void ResetValue(object component) {
((PropertyBag)component)[Name] = null;
}
public override bool CanResetValue(object component) {
return true;
}
public override bool ShouldSerializeValue(object component)
{ // *** this controls whether it appears bold or not; you could compare
// *** to a default value, or the last saved value...
return ((PropertyBag)component)[Name] != null;
}
public override Type PropertyType {
get { return typeof(string); }
}
public override bool IsReadOnly {
get { return false; }
}
public override Type ComponentType {
get { return typeof(PropertyBag); }
}
}
[TypeConverter(typeof(PropertyBagConverter))]
class PropertyBag {
public string[] GetKeys() {
string[] keys = new string[values.Keys.Count];
values.Keys.CopyTo(keys, 0);
Array.Sort(keys);
return keys;
}
private readonly Dictionary<string, string> values
= new Dictionary<string, string>();
public string this[string key] {
get {
string value;
values.TryGetValue(key, out value);
return value;
}
set {
if (value == null) values.Remove(key);
else values[key] = value;
}
}
}
// has the job of (among other things) providing properties to the PropertyGrid
class PropertyBagConverter : TypeConverter {
public override bool GetPropertiesSupported(ITypeDescriptorContext context) {
return true; // are we providing custom properties from here?
}
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, System.Attribute[] attributes) {
// get the pseudo-properties
PropertyBag bag = (PropertyBag)value;
string[] keys = bag.GetKeys();
PropertyDescriptor[] props = Array.ConvertAll(
keys, key => new PropertyBagPropertyDescriptor(key));
return new PropertyDescriptorCollection(props, true);
}
}
static class Program {
[STAThread]
static void Main() { // demo form app
PropertyBag bag = new PropertyBag();
bag["abc"] = "def";
bag["ghi"] = "jkl";
bag["mno"] = "pqr";
Application.EnableVisualStyles();
Application.Run(
new Form {
Controls = { new PropertyGrid {
Dock = DockStyle.Fill,
SelectedObject = bag
}}
});
}
}