.net - PropertyGrid - 可以定制吗?

标签 .net winforms .net-2.0 propertygrid

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

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

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

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

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

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

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

是否可以隐藏所有属性并仅指示一些应该存在的属性?

最佳答案

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

使用 TypeConverter您可以控制 PropertyGrid 中属性和/或对象的外观和感觉。您可以使用它来添加“虚拟”属性,或忽略属性。属性的名称也可以更改/本地化。但与其他选项相比,类型转换器的实现有些困难。

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 (丑陋的名字,我知道)类中,以包含数据类型和本地化标签。

关于.net - PropertyGrid - 可以定制吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3021272/

相关文章:

c# - Lambda 表达式的位置在延迟初始化中是否重要?

c# - 如何在不打开新窗口的情况下在表单之间切换? C# 语言

c# - 如何使用反射设置类型为 List<CustomClass> 的属性

c# - 如何从一个 Visual Studio 项目创建两个不同的可执行文件

c# - 一个艰难的表格转换成 XML

c# - 如何重用 Type 返回值生成新的源代码

c# - Entity Framework Brainmush Kerfuffle 壮观

c# - 如何在ItemsControl中显示弹出窗口

javascript - 如何通过 .Net 共享主机上的 URL 运行 EXE 文件

c# - 将 IconAlignment 与 WinForms ErrorProvider 一起使用时出现的问题