优化属性网格的类

本文关键字:网格 属性 优化 | 更新日期: 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; } 
     }
}