Как создать просматриваемые свойства класса в. NET / Visual studio - PullRequest
7 голосов
/ 02 марта 2020

Как я могу сделать что-то подобное в окне свойств VS (складные мульти свойства):

enter image description here

Я пробовал такой код:

   Test z = new Test();

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

Где класс "Test":

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

Но это дает мне только серое имя класса

enter image description here

Ответы [ 3 ]

4 голосов
/ 05 марта 2020

Хорошо, у меня есть кое-что для работы, которое может удовлетворить ваш случай.

Чтобы получить класс для расширения в 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; }
}

Это просто опустошает информацию и предотвращает пользователь вводит какое-то другое значение. Вы, вероятно, хотите показать что-то более наглядное, что полностью зависит от вас.
Также возможно получить информацию и разобрать ее на полезные значения. Хорошим примером может служить местоположение, представляющее собой объект типа Point, визуализируемый с помощью [10,5], когда X равно 10 и Y равно 5. Когда вы вводите новые значения, они анализируются и устанавливаются в целые числа, на которые ссылается исходная строка.


Поскольку я не мог найти много о topi c, я посмотрел некоторые ссылки в ReferenceSource , потому что это нужно было сделать раньше. В моем случае я заглянул в ButtonBase и FlatButtonAppearance WindowsForms, чтобы посмотреть, как Microsoft сделала это, в тот день.

Надеюсь, что смогу помочь.

3 голосов
/ 05 марта 2020

Вот класс 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, если вы включаете категорию или описание товара.

enter image description here

Приветствия!

1 голос
/ 05 марта 2020

Помимо уже хороших ответов других.

Доступный для просмотра (true / false) означает, что его можно просмотреть в окне свойств. Обратите внимание, что редактор свойств Visual Studio покажет только свойства publi c. Частные объекты скрыты и не могут быть просмотрены по разным причинам. Свойства

Publi c доступны для просмотра по умолчанию. 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

...