【问题标题】:How to create browseable class-properties in .NET / Visual studio如何在 .NET / Visual Studio 中创建可浏览的类属性
【发布时间】:2020-06-15 04:24:29
【问题描述】:

我如何在 VS 属性窗口(可折叠的多属性)中制作这样的东西:

我试过这样的代码:

   Test z = new Test();

    [ Browsable(true)]
    public Test _TEST_ {
        get { return z; }
        set { z = value; }
    }

“测试”类在哪里:

[Browsable(true)] 
public class Test {
    [Browsable(true)] 
    public string A { get;set; }
    [Browsable(true)] 
    public string B { get;set; }
}

但这只给了我类的灰色名称

【问题讨论】:

  • 您是否尝试改用DebuggerDisplayAttribute 或/和DebuggerBrowsableAttributeEnhancing Debugging with the Debugger Display Attributes
  • 别介意第一条评论。它更多的是关于调试窗口而不是属性窗口。也许这将是您弄清楚如何做的更好的链接。 Extend properties
  • 如您所见 - 这不是我想要的。我想我可能需要在这里定义类型的编辑器帮助属性窗口
  • 还没弄明白,但我认为这很重要:[TypeConverter(typeof(SizeConverter))]

标签: c# .net visual-studio user-interface components


【解决方案1】:

好的,我有一些工作可以满足你的情况。

要在 PropertyGrid 中扩展类,您必须向其添加 TypeConverterAttribute,引用 ExpandableObjectConverter 的类型(或派生自它的其他内容)。

[TypeConverter(typeof(ExpandableObjectConverter))]
public class Test
{
    [Browsable(true)]
    public string A { get; set; }
    [Browsable(true)]
    public string B { get; set; }
}

唯一的问题是它现在显示类型名称(其ToString() 方法的返回值作为您的类的值)。您可以接受它(您可能不想这样做),将 ToString() 返回值更改为更合适的值,或者针对这种情况使用自定义 TypeConverter

我将向您展示如何完成后者的快速实现:

internal class TestConverter : ExpandableObjectConverter
{
    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        if (destinationType == typeof(string))
            return "";
        return base.ConvertTo(context, culture, value, destinationType);
    }
}

然后你会写这个,而不是我上面写的:

[TypeConverter(typeof(TestConverter))]
public class Test
{
    [Browsable(true)]
    public string A { get; set; }
    [Browsable(true)]
    public string B { get; set; }
}

这只是清空信息并阻止用户输入其他值。您可能想要展示更具描述性的内容,这完全取决于您。
也可以获取信息并将其解析为有用的值。一个很好的例子是位置,当X10 并且Y5 时,它是Point 类型的对象,用[10,5] 可视化。当您输入新值时,它们会被解析并设置为原始字符串引用的整数。


因为找不到太多关于该主题的内容,所以我在ReferenceSource 中查找了一些参考资料,因为它必须在之前完成。就我而言,我查看了 WindowsForms 的 ButtonBaseFlatButtonAppearance,以了解微软当年是如何做到的。

希望我能帮上忙。

【讨论】:

    【解决方案2】:

    这里是 TypeConverter 类。这允许 VS 属性以字符串的形式访问您的对象,并从字符串转换回它。

    更多关于TypeConversion的信息。

    class MultiPropConverter : ExpandableObjectConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context,
        Type sourceType)
        {
            if (sourceType == typeof(string)) { return true; }
            return base.CanConvertFrom(context, sourceType);
        }
    
        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture,
            object value)
        {
            if (value is string)
            {
                string[] v = ((string)value).Split(new char[] { ',' });
                if(v.Length == 3) // Check that there are no ',' in your string(s) A.
                {
                    return new DropDownProperties(v[0], float.Parse(v[1]), int.Parse(v[2]));
                }
            }
            return base.ConvertFrom(context, culture, value);
        }
    
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture,
            object value, Type destinationType)
        {
            if (destinationType == typeof(string)) // What VS properties ask for to display
            {
                DropDownProperties dDP = (DropDownProperties)value;
                return dDP.A + "," + dDP.B.ToString() + "," + dDP.C.ToString();
            }
            return base.ConvertTo(context, culture, value, destinationType);
        }
    }
    

    多属性类:

    [TypeConverter(typeof(MultiPropConverter))]
    public class DropDownProperties
    {       
        [Description("Description of A")]
        public string A { get; set; } = "Default";      
        [Description("Description of B")]
        public float B { get; set; } = 0f;
        [Description("Description of C")]
        public int C { get; set; } = 1;
    }
    

    然后是类实例化:

        [Description("Category Description"), Category("ACategory")]
        public DropDownProperties dropProp { get; set; } = new DropDownProperties() 
        { A = "Hello World", B = "0.1", C = 0};
    

    如果您包含项目的类别或描述,则不需要 Browsable 属性。

    干杯!

    【讨论】:

      【解决方案3】:

      除了其他人已经很好的答案。

      Browseable(true/false) 表示可以在属性窗口中浏览。 请注意,Visual Studio 属性编辑器只会显示公共属性。私有属性是隐藏的,由于各种原因无法浏览。

      默认情况下可浏览公共属性。 https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.browsableattribute?view=netcore-3.1

      设计器将始终只为字符串显示一个默认值,多属性下拉列表仅适用于整数 afaik。

      此外,还有 EditorBrowsable 可定义 Intellisense 是否显示您的属性。

      你可以这样做:

      public class Column
      {
          [EditorBrowsable(EditorBrowsableState.Always)]
          public string name { get; set; }
          [EditorBrowsable(EditorBrowsableState.Never)]
      }
      

      https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.editorbrowsablestate?view=netcore-3.1 https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.editorbrowsableattribute?view=netcore-3.1

      【讨论】:

      • 这个问题的属性是公开的,多属性下拉列表只适用于整数是不正确的,因为我在答案中已经清楚地表明了这一点。
      • 应该添加“默认”
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-30
      • 1970-01-01
      • 2011-04-21
      相关资源
      最近更新 更多