1

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

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

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

如何获得PropertyGridFoo 的友好版本?

我已经尝试过从它继承(将其命名为 FooDesignable)并用所需的属性隐藏它的属性。但是,直到我发现 Foo 正在使用库项目的其他自定义类,然后我也不得不隐藏并更改 Foo 中的现有属性以返回 XxxDesignable 类型,这并没有很好地工作。

我在这里陷入了死胡同吗?还是我只是想不好?

4

2 回答 2

2

您可以做的是重用DynamicTypeDescriptor我在此处对这个问题的回答中描述的类 SO: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();
    }
}
于 2013-09-26T16:29:27.730 回答
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; } 
     }
}
于 2013-09-26T16:26:18.040 回答