如何在Winform Designer中保存用户控件的结构类型属性?

时间:2019-03-08 09:01:04

标签: c# winforms struct windows-forms-designer

我检查了这个问题的答案: Modifying structure property in a PropertyGrid

还有.net的SizeConverter

但没有帮助,我的财产仍未保存。


我有一个结构,一个用户控件和一个自定义类型转换器。

public partial class UserControl1 : UserControl
{
    public Bar bar { get; set; } = new Bar();
}

[TypeConverter(typeof(BarConverter))]
public struct Bar
{
    public string Text { get; set; }
}

public class BarConverter : ExpandableObjectConverter
{
    public override bool GetCreateInstanceSupported(ITypeDescriptorContext context)
    {
        return true;
    }

    public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues)
    {
        if (propertyValues != null && propertyValues.Contains("Text"))
            return new Bar { Text = (string)propertyValues["Text"] };
        return new Bar();
    }
}

编译后,我将控件拖动到一个窗体中,然后可以看到属性窗口中显示的属性Bar.Text,也可以编辑该值,它似乎已保存。


但是在InitializeComponent方法中什么也没有产生

nothing generated

因此,如果我重新打开设计器,则属性窗口中的“文本”字段将变为空。

请注意,该结构没有自定义构造函数,因此我无法使用InstanceDescriptor

我错过任何重要的步骤吗?

1 个答案:

答案 0 :(得分:1)

您在类型描述符中缺少一些方法覆盖:

public class BarConverter : ExpandableObjectConverter
{
    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        if (destinationType == typeof(InstanceDescriptor))
            return true;
        return base.CanConvertTo(context, destinationType);
    }
    public override object ConvertTo(ITypeDescriptorContext context, 
        CultureInfo culture, object value, Type destinationType)
    {
        if (destinationType == typeof(InstanceDescriptor))
        {
            ConstructorInfo ci = typeof(Bar).GetConstructor(new Type[] { typeof(string) });
            Bar t = (Bar)value;
            return new InstanceDescriptor(ci, new object[] { t.Text });
        }
        return base.ConvertTo(context, culture, value, destinationType);
    }
    public override object CreateInstance(ITypeDescriptorContext context, 
        IDictionary propertyValues)
    {
        if (propertyValues == null)
            throw new ArgumentNullException("propertyValues");
        object text = propertyValues["Text"];
        return new Bar((string)text);
    }
    public override bool GetCreateInstanceSupported(ITypeDescriptorContext context)
    {
        return true;
    }
}

并将构造函数添加到struct中:

[TypeConverter(typeof(BarConverter))]
public struct Bar
{
    public Bar(string text)
    {
        Text = text;
    }
    public string Text { get; set; }
}

这是Bar属性序列化的方式:

// 
// userControl11
// 
this.userControl11.Bar = new SampleWinApp.Bar("Something");

bar属性将如下图所示显示在属性网格中,其中Text属性是可编辑的:

enter image description here

您可能还想通过覆盖结构的ToString()方法来为结构提供更好的字符串表示形式,并通过覆盖CanConvertFrom和{ {1}},例如PointConverterSizeConverter