TypeConverter.ConvertFrom вызывается все время, мне нужно выполнить преобразование только один раз, когда пользователь выбирает значение.
Я хочу иметь возможность отображать объект в элементе управления PropertyGrid, чтобы вы могли видеть и изменять дочерние значения в нем. Атрибуция свойства с ExpandableObjectConverter делает это. Я также хочу иметь возможность выбирать различные значения из выпадающего списка, чтобы установить объект. Расширяя ExpandableObjectConverter и реализуя GetStandardValues и ConvertFrom, я могу заставить это работать.
В моем примере я использую описательные значения для GetStandardValues, а затем преобразовываю их в целевые объекты в ConvertFrom. Однако объекты, которые мне нужно создать, имеют значительные ресурсы, поэтому я не хочу создавать какие-либо из них, пока они не будут выбраны в пользовательском интерфейсе.
У меня проблема в том, что PropertyGrid вызывает ConvertFrom несколько раз, а не просто для преобразования выбранного результата в целевой тип (см. Журнал ниже).
Я хочу достичь того, что изображено здесь, но создать базовый объект только тогда, когда пользователь фактически делает выбор.
![Required Property grid functionality](https://i.stack.imgur.com/r1L7f.png)
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