优化PropertyGrid的类

时间:2013-09-26 15:58:05

标签: c# winforms propertygrid

我在GUI项目中使用的库中定义了一个类Foo。 GUI项目允许在System.Windows.Forms.PropertyGrid

的帮助下对Foo实例进行图形编辑

为了在PropertyGrid中编辑Foo类的实例,我必须为Foo的属性设置几个属性,例如Browsable

但是,我不想在Foo中设置这些属性,因为它所在的库应该只包含在代码中使用Foo所需的东西(而不是在GUI中)。

如何获得PropertyGrid友好版的Foo?

我已经尝试从它继承(命名为FooDesignable)并使用所需属性隐藏其属性。但是,直到我发现Foo正在使用库项目的其他自定义类,然后我也不得不影子,并且更改Foo中的现有属性以返回XxxDesignable类型时,这种方法效果不好。

我在这里走到了尽头吗?或者我只是在想它呢?

2 个答案:

答案 0 :(得分:1)

您可以做的是重新使用我在这个问题的答案中描述的DynamicTypeDescriptor课程:PropertyGrid Browsable not found for entity framework created property, how to find it?

就像这样:

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();
    }
}

答案 1 :(得分:0)

我认为你有正确的想法来创建另一种类型,但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; } 
     }
}