具有下拉列表和自定义TypeConverter的PropertyGrid。停止多次调用ConvertFrom

时间:2019-03-15 17:08:17

标签: c# winforms propertygrid typeconverter

TypeConverter.ConvertFrom一直被调用,当用户选择一个值时,我只需执行一次转换。

我希望能够在PropertyGrid控件中显示对象,以便您可以查看和更改其中的子值。使用ExpandableObjectConverter将该属性归因于此。我还希望能够从下拉列表中选择不同的值以设置对象。通过扩展ExpandableObjectConverter并实现GetStandardValues和ConvertFrom,我可以使其工作。

在我的示例中,我对GetStandardValues使用描述性值,然后将其转换为ConvertFrom中的目标对象。但是,我需要创建的对象会占用大量资源,因此,在UI中选择它们之前,我不想创建任何对象。

我遇到的问题是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

0 个答案:

没有答案