【问题标题】:Optimize class for PropertyGrid优化 PropertyGrid 类
【发布时间】:2013-09-26 15:58:04
【问题描述】:

我在 GUI 项目中使用的库中定义了一个类 Foo。 GUI 项目允许在 System.Windows.Forms.PropertyGrid 的帮助下对 Foo 的实例进行图形编辑。

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

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

如何获得PropertyGrid 友好版本的 Foo?

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

我是不是走投无路了?还是我只是想不好?

【问题讨论】:

    标签: c# winforms propertygrid


    【解决方案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();
        }
    }
    

    【讨论】:

    • 您能否举例说明如何将 Editor 属性添加到类的属性中?我似乎有点困惑;o
    【解决方案2】:

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

    【讨论】:

    • 这比我的想法更好,但正如你所说,如果涉及多个自定义类,其中一些在通用列表中,它会变得有点复杂。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-10
    相关资源
    最近更新 更多