【问题标题】:Special meaning of property "Name" within a property grid属性网格中属性“名称”的特殊含义
【发布时间】:2014-02-13 09:47:01
【问题描述】:
  • 我使用 PropertyGrid 允许最终用户编辑类 ClassA 中的属性
  • 这个类有一个List<ClassB> 属性。
  • 对于List<ClassB> 属性,PropertyGrid 显示(Collection) 和一个带有3 个点的按钮,该按钮会打开一个如下所示的新窗口(取自another SO post)。

  • 我想自定义左侧的Members: DisplayName,所以对于ClassB,我已经覆盖了ToString() 方法

    public class ClassB
    {
        public string Name { get; set; }
        public TimeSpan Value { get; set; }
    
        public override ToString() { return String.Format("{0} ({1})", this.Name, this.Value); }
    }
    

现在问题来了:

  • 如果 Name 为空,则按预期显示 (00:00:00)
  • 如果我将名称更改为测试,我希望它显示Test (00:00:00),但它只显示Test
  • 如果我将属性名称重命名为其他名称,它会按预期工作。

我想这是一个特殊的约定,如果一个类有一个属性 Name 并且值不为 null 或空,控件会显示这个属性而不是名称。

但是,我还没有找到可以验证这一点的文档,而且我不知道如何改变这种行为。我如何做到这一点?

注意:更改属性名称不是一种选择。

【问题讨论】:

    标签: c# .net winforms propertygrid


    【解决方案1】:

    不幸的是,CollectionEditor.GetDisplayText Method 中的逻辑非常硬编码。它没有记录,但您可以使用工具对其进行拆卸。这是代码:

    protected virtual string GetDisplayText(object value)
    {
        string str;
        if (value == null)
            return string.Empty;
    
        // use the Name property
        PropertyDescriptor defaultProperty = TypeDescriptor.GetProperties(value)["Name"];
        if ((defaultProperty != null) && (defaultProperty.PropertyType == typeof(string)))
        {
            str = (string) defaultProperty.GetValue(value);
            if ((str != null) && (str.Length > 0))
            {
                return str;
            }
        }
    
        // or use the DefaultPropertyAttribute
        defaultProperty = TypeDescriptor.GetDefaultProperty(this.CollectionType);
        if ((defaultProperty != null) && (defaultProperty.PropertyType == typeof(string)))
        {
            str = (string) defaultProperty.GetValue(value);
            if ((str != null) && (str.Length > 0))
            {
                return str;
            }
        }
    
        // or use the TypeConverter
        str = TypeDescriptor.GetConverter(value).ConvertToString(value);
        if ((str != null) && (str.Length != 0))
        {
            return str;
        }
    
        // or use the type name
        return value.GetType().Name;
    }
    

    这段代码很讨厌,因为它基本上是反其道而行之。它应该使用 Name 属性作为最后的手段,而不是专注于它......

    但由于 CollectionEditor 类未密封,所有希望都不会丢失。这是你可以解决它的方法:

    1) 在保存集合的类上声明 EditorAttribute,如下所示:

    public class ClassA
    {
        [Editor(typeof(MyCollectionEditor), typeof(UITypeEditor))]
        public List<ClassB> List { get; set; }
    }
    

    2) 像这样定义您的自定义集合编辑器;

    public class MyCollectionEditor : CollectionEditor // needs a reference to System.Design
    {
        public MyCollectionEditor(Type type)
            : base(type)
        {
        }
    
        protected override string GetDisplayText(object value)
        {
            // force ToString() usage, but
            // you also could implement some custom logic here
            return string.Format("{0}", value);
        }
    }
    

    【讨论】:

    • This code is pretty nasty because it does things basically the other way around 我完全同意,顺序:DefaultPropertyAttribute、TypeConverter、Name 属性、Type Name 会更有意义。
    猜你喜欢
    • 1970-01-01
    • 2020-09-23
    • 1970-01-01
    • 2012-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多