PropertyGrid - 它可以自定义吗?

时间:2010-06-11 08:23:58

标签: .net winforms .net-2.0 propertygrid

我有一个项目,我们必须在WYSIWYG中的用户控件上表示一些图形对象。还需要编辑每个对象属性(颜色,位置等)。

alt text http://lh6.ggpht.com/_1TPOP7DzY1E/TBHz8PW8MQI/AAAAAAAADPE/kzAbKKsEkmU/s144/Untitled.gif

我在使用PropertyGrid('直接'属性编辑)和DoubleClick上的自定义表单('间接'编辑)之间犹豫不决。

PropertyGrid很好,但应该符合一些标准:

  • 仅选定的属性 显示(例如,如果我有 TextRectangle只想显示 文字和位置);
  • 物业名称 应该是可定制的 国际化的(通过例如 TextRectangle Text属性应该是 命名为“公司名称”或“Название предприятия“)。

现在我有可能认为答案可能是肯定的,但如果我们没有很多时间,使用它是否合理。什么可以更快实现,自定义表单或属性面板?

编辑:
我在互联网上看到的最多的例子是完全自定义对象女巫属性可以轻松管理。我遇到的问题是我还会显示我无法控制的.NET Framework对象,如TextBoxes,Label,RectangleShape或OvalShape(VB.Powerpacks)

是否有可能隐藏所有属性并仅指出应该存在的几个属性?

3 个答案:

答案 0 :(得分:2)

可以使用显示的类上的属性自定义PropertyGrid。

使用TypeConverter,您可以控制外观&感觉PropertyGrid中的属性和/或对象。您可以使用它来添加“虚拟”属性,或者保留属性。此外,可以更改/本地化属性的名称。但是,作为其他选择,Typeconverter实施起来有点困难。

使用UITypeEditor,您可以控制如何编辑属性(内联,显示您自己的对话框,颜色选择器......)

您可以将DisplayName附加到媒体资源,以更改名称。如果您覆盖该类,则可以翻译属性名称。 This question has an example how to do this.

并且(像Rune Grimstad回答的那样)你通过在它们上面加上[Browsable(false)]属性来省略属性。

另一个不错的是DefaultValue,如果属性的值与DefaultValue提供的值匹配,则该值使用普通字体。如果不同,则使用粗体字体。

您的问题是您不想一直从TextBox或其他类继承。您可以将文本框封装在一个包装器中,该包装器仅公开(通过TypeConverter)您需要的属性。我已经破解了这样做的事情:

class BaseWrapper<T> {
    public BaseWrapper(T tb) {
        this.Wrapped = tb;
    }

    [Browsable(false)]
    public T Wrapped { get; set; }

    public object GetMember(string name) {
        var prop = this.Wrapped.GetType().GetProperty(name);
            return prop.GetValue(this.Wrapped, null);
    }

    public void SetMember(string name, object value) {
        var prop = this.Wrapped.GetType().GetProperty(name);
        prop.SetValue(this.Wrapped, value, null);
    }
}

class BaseConverter<T> : TypeConverter {
    protected class pd : SimplePropertyDescriptor {
        public pd(string displayName, string name) : base(typeof(BaseWrapper<T>), displayName, typeof(string)) {
            this.PropName = name;

        }
        public string PropName { get; set; }

        public override object GetValue(object component) {
            var wrapper = (BaseWrapper<T>)component;
            return wrapper.GetMember(this.PropName);
        }
        public override void SetValue(object component, object value) {
            var wrapper = (BaseWrapper<T>)component;
            wrapper.SetMember(this.PropName, value);
        }
    }
    public override bool GetPropertiesSupported(ITypeDescriptorContext context) {
        return true;
    }
}

[TypeConverter(typeof(TextBoxConverter))]
class TextboxWrapper : BaseWrapper<TextBox> {
    public TextboxWrapper(TextBox t) : base(t) { }
}

class TextBoxConverter : BaseConverter<TextBox> {
    public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) {
        return new PropertyDescriptorCollection(new PropertyDescriptor[] {
            new pd("Название предприятия", "Text")
        });
    }
}

要使文本框成为所选对象,请使用:

this.propertyGrid1.SelectedObject = new TextboxWrapper(this.textBox1);

进一步解决这个问题的地方是pd(丑陋的名字,我知道)类,包括数据类型和本地化标签。

答案 1 :(得分:1)

属性网格将检查某些属性的选定对象属性:

这意味着您可以隐藏某些属性并部分控制属性的显示方式,但据我所知,您无法添加自定义或已翻译的属性名称。

Check the docs on MSDN for more information

编辑: 您应该查看有关全球化属性网格的this article on Codeproject。它似乎做你想要的。

答案 2 :(得分:1)

您可以在CodeProject上查看this article。它使用通用的PropertyBag对象来包含要从对象公开的任何属性,并将PropertyBag提供给PropertyGrid以显示。