PropertyGrid с выпадающим списком и пользовательским TypeConverter.Стоп ConvertFrom вызывается несколько раз - PullRequest
0 голосов
/ 15 марта 2019

TypeConverter.ConvertFrom вызывается все время, мне нужно выполнить преобразование только один раз, когда пользователь выбирает значение.

Я хочу иметь возможность отображать объект в элементе управления PropertyGrid, чтобы вы могли видеть и изменять дочерние значения в нем. Атрибуция свойства с ExpandableObjectConverter делает это. Я также хочу иметь возможность выбирать различные значения из выпадающего списка, чтобы установить объект. Расширяя ExpandableObjectConverter и реализуя GetStandardValues ​​и ConvertFrom, я могу заставить это работать.

В моем примере я использую описательные значения для GetStandardValues, а затем преобразовываю их в целевые объекты в ConvertFrom. Однако объекты, которые мне нужно создать, имеют значительные ресурсы, поэтому я не хочу создавать какие-либо из них, пока они не будут выбраны в пользовательском интерфейсе.

У меня проблема в том, что PropertyGrid вызывает ConvertFrom несколько раз, а не просто для преобразования выбранного результата в целевой тип (см. Журнал ниже).

Я хочу достичь того, что изображено здесь, но создать базовый объект только тогда, когда пользователь фактически делает выбор.

Required Property grid functionality

PropertyGridCtrl.SelectedObject = new MyContainer();

...

public class MyContainer
{
    [TypeConverterAttribute(typeof(ExpandableObjectConverterWithPicker))]
    public MyExpensiveObjectToCreate SlowCreationObj { get; set; } = new MyExpensiveObjectToCreate("Original");
}

public class MyExpensiveObjectToCreate
{
    public MyExpensiveObjectToCreate(string value)
    {
        Debug.WriteLine("Creating Expensive Object : " + value);
        this.Value = value;
        Thread.Sleep(1000);
    }

    public string Value { get; set; } = "test";
    public override string ToString() { return this.Value; }
}

public class ExpandableObjectConverterWithPicker : ExpandableObjectConverter
{
    public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) { return true; }
    public override bool GetStandardValuesSupported(ITypeDescriptorContext context) { return true; }
    public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
    {
        return new StandardValuesCollection(new string[] { "Description of Object 1", "Description of Object 2" });
    }

    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
    }
    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        if (value is string strVal)
        {
            if (strVal == "Description of Object 1")
                return new MyExpensiveObjectToCreate("Object 1");
            else if (strVal == "Description of Object 2")
                return new MyExpensiveObjectToCreate("Object 2");
            else
                throw new NotSupportedException();
        }
        return base.ConvertFrom(context, culture, value);
    }
}

Журнал отладки при выборе значения из раскрывающегося списка

Creating Expensive Object : Original
Creating Expensive Object : Object 1
Creating Expensive Object : Object 1
Creating Expensive Object : Object 1
Creating Expensive Object : Object 1
Creating Expensive Object : Object 1
Creating Expensive Object : Object 2
Creating Expensive Object : Object 1
Creating Expensive Object : Object 1
Creating Expensive Object : Object 2
Creating Expensive Object : Object 2
Creating Expensive Object : Object 2
...