Wpf.PropertyGrid ComboBox из массива строк в пользовательских атрибутах - PullRequest
0 голосов
/ 03 апреля 2019

Предположим, у меня есть следующий пользовательский атрибут оформленный класс, который реализует TypeConverter. Я хотел бы создать поле со списком в Wpf.PropertyGrid так, чтобы значения в поле со списком были взяты из массива строк, указанного в пользовательском атрибуте. Проблема, с которой я сталкиваюсь, заключается в том, что, хотя я могу перебирать все свойства с помощью пользовательского атрибута, я не могу определить фактическое свойство, которое вызвало TypeConverter, поскольку context.PropertyGrid имеет значение null. Можно ли создать такой комбинированный список? Если да, то как?

Класс:

[TypeConverter(typeof(ExpandableObjectConverter))]
public class Animals : INotifyPropertyChanged
{
    // Constructor
    public Animals()
    {
        foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(this))
        {
            DefaultValueAttribute attr = (DefaultValueAttribute)prop.Attributes[typeof(DefaultValueAttribute)];
            if (attr != null)
                prop.SetValue(this, attr.Value);
        }
    }

    // Properties
    private string _pets, _others;

    // both properties have the same TypeConverter, but they use different custom attributes
    [RefreshProperties(RefreshProperties.All)]
    [TypeConverter(typeof(ListTypeConverter))]
    [ListTypeConverterAttribute(new [] { "cat", "dog" })]
    [ListTypeConverterAttribute(new [] { "cat1", "dog1" })]
    [DefaultValue("cat")]
    public string Pets
    {
        get { return _pets; }
        set { SetField(ref _pets, value); }
    }

    [RefreshProperties(RefreshProperties.All)]
    [ListTypeConverterAttribute(typeof(ListTypeConverter))]
    [ListTypeConverterAttribute(new [] { "cow", "sheep" })]
    [DefaultValue("sheep")]
    public string Others
    {
        get { return _others; }
        set { SetField(ref _others, value); }
    }

    // Methods
    public override string ToString()
    {
        return string.Empty;
    }

    // ----- Implement INotifyPropertyChanged -----
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }

    protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
    {
        if (EqualityComparer<T>.Default.Equals(field, value))
            return false;
        field = value;
        OnPropertyChanged(propertyName);
        return true;
    }
}

Пользовательский атрибут:

public sealed class ListTypeConverterAttribute : Attribute
{
    public ListTypeConverterAttribute(params string[] list)
    {
        this.List = list;
    }

    public string[] List { get; set; }

    public override object TypeId
    {
        get { return this; }
    }
}

TypeConverter:

public class ListTypeConverter : TypeConverter
{
    public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
    {
        return true;
    }

    public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
    {
        return true;
    }

    public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
    {
        base.GetStandardValues(context);

        List<string> list = new List<string>();

        // HERE IS MY ISSUE ...
        // How do I get the property invoking the TypeConverter so I can get its list?
        // context.PropertyGrid == null

        return new StandardValuesCollection(list);
    }
}
...