c# - 属性网格中属性 "Name"的特殊含义

标签 c# .net winforms propertygrid

  • 我使用 PropertyGrid 来允许最终用户编辑类的属性 ClassA
  • 该类(class)有 List<ClassB>属性(property)。
  • 对于List<ClassB>属性,PropertyGrid 显示 (Collection)和一个带有 3 个点的按钮,用于打开一个新窗口,如下所示(取自 another SO post )。

enter image description here

  • 我想自定义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); }
    }
    

现在问题来了:

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

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

但是,我还没有找到可以验证这一点的文档,并且我不知道如何更改此行为。我该如何实现这一目标?

注意:更改属性名称不是一个选项。

最佳答案

不幸的是,逻辑在 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);
    }
}

关于c# - 属性网格中属性 "Name"的特殊含义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21750513/

相关文章:

c# - 你如何在 C# 中隐藏封装?

c# - 如何验证 DropDownList 中的选定值?

c# - 如何将组合硬编码片段转换为递归函数?

.net - IP 更改后重新连接已删除的 SqlConnection,而不回滚事务

c# - 使多个矩形或区域无效

c# - 如何在连接局域网的其他计算机上使用SQL Server数据库运行桌面应用程序

c#/Linq 总和在哪里

asp.net - 格式化此日期时间,不带秒或 AM/PM

c# - 检查非打字间隔

c# - 在设计时将换行符添加到标签的文本