优化属性网格的类
本文关键字:网格 属性 优化 | 更新日期: 2023-09-27 18:32:59
我在GUI项目中使用的库中定义了一个类Foo。GUI项目允许在System.Windows.Forms.PropertyGrid
的帮助下对Foo实例进行图形编辑。
为了使在PropertyGrid
中编辑类 Foo 的实例变得舒适,我必须为 Foo 的属性设置几个属性,例如Browsable
。
但是,我不想在Foo中设置这些属性,因为它所在的库应该只具有在代码中使用Foo(而不是GUI)所需的东西。
如何获得 Foo 的PropertyGrid
友好版本?
我已经尝试从它继承(将其命名为 FooDesignable)并使用所需的属性隐藏其属性。然而,这并没有很好地工作很长时间,直到我发现Foo正在使用库项目的其他自定义类,然后我也必须隐藏这些类,并更改Foo中的现有属性以返回XxxDesignable类型。
我在这里是死胡同吗?还是我只是想坏了?
您可以做的是重用我在SO上回答此问题时描述的DynamicTypeDescriptor
类:找不到实体框架创建的属性的PropertyGrid可浏览属性,如何找到它?
例如,像这样:
public Form1()
{
InitializeComponent();
DynamicTypeDescriptor dt = new DynamicTypeDescriptor(typeof(MyBeautifulClass));
// initialize the class the way you want
MyBeautifulClass c = new MyBeautifulClass();
c.MyProperty = "hello world";
// we need to replace a property by another version, so let's remove the existing one
dt.RemoveProperty("MyProperty");
// create a new similar property with a new editor and the current value
dt.AddProperty(
typeof(string), // type
"MyProperty", // name
c.MyProperty, // value
"My Property", // display name
"My Property Description", // description
"My Category", // category
false, // has default value?
null, // default value
false, // readonly?
typeof(MyEditor)); // editor
// create a wrapped object from the original one.
// unchanged properties will keep their current value
var newObject = dt.FromComponent(c);
// hook on value change
newObject.PropertyChanged += (sender, e) =>
{
// update the original object
// note: the code could be made more generic
c.MyProperty = newObject.GetPropertyValue<string>(e.PropertyName, null);
};
propertyGrid1.SelectedObject = newObject;
}
public class MyBeautifulClass
{
public string MyProperty { get; set; }
}
// this stupid sample editor puts a current string in upper case... :-)
public class MyEditor : UITypeEditor
{
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.Modal;
}
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
return value == null ? value : value.ToString().ToUpper();
}
}
我认为
您有制作另一种类型的正确想法,但FooDesigner
应该是一个包装器,而不是从Foo
继承。这样,您就可以将复杂对象包装在它们自己的包装器类型中。如果您要包装很多类,这可能会变得乏味。您可能需要查看 T4 模板来帮助为包装类生成框架。下面是一个示例:
class FooDesigner
{
private Foo foo;
public FooDesigner(Foo foo)
{
this.foo = foo;
}
public int Prop1
{
get { return foo.Prop1; }
set { foo.Prop1 = value; }
}
public BarDesigner Bar { get { return new BarDesigner(foo.Bar); } }
}
class BarDesigner
{
private Bar bar;
public BarDesigner(Bar bar)
{
this.bar = bar;
}
public string Prop2
{
get { return bar.Prop2; }
set { bar.Prop2 = value; }
}
}