序列化在设计时从UITypeEditor设置的自定义类型

时间:2017-11-10 14:05:43

标签: c# winforms generics windows-forms-designer uitypeeditor

您好我有一个自定义的genric表单,自定义类型和UITypeEditor以及它的表单。

我可以在设计时设置和编辑自定义类型的列表。我的问题是。设置后,它没有序列化到designer.cs文件。

我在这里错过了什么吗?

MyCustomForm:

 public partial class MyBrowseForm<TParentEntity> : Form where TParentEntity:class
{


    private BindingList<MyBindingFields> _myBindingFieldsCollection = new BindingList<MyBindingFields>();

   [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    [Editor(typeof(BdFormTypeEditor), typeof(UITypeEditor))]
    [TypeConverter(typeof(ExpandableObjectConverter))]        
    public BindingList<MyBindingFields> MyBindingFieldsCollection
    {
        get => _myBindingFieldsCollection;
        set => _myBindingFieldsCollection = value;
    }
}

TypeEditor

class BdFormTypeEditor : UITypeEditor
{
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
        return UITypeEditorEditStyle.Modal;
    }
    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
    {        
        var svc = provider.GetService(typeof(IWindowsFormsEditorService))
            as IWindowsFormsEditorService;

        BindingList<MyBindingFields> bindingFieldsList = context.Instance.GetPropValue("MyBindingFieldsCollection") as BindingList<MyBindingFields>;

        var myGenericTypeProperty = context?.Instance.GetType()
        .GetProperty("MyGenericType");                         
        var genericArgument = (Type)myGenericTypeProperty.GetValue(context.Instance);
        var editorFormType = typeof(MyEditorForm<>);
        var genericArguments = new[] { genericArgument };
        var editorFormInstance = editorFormType.MakeGenericType(genericType);
        if (svc != null)
        {
            using (var f = (Form) Activator.CreateInstance(editorFormInstance))
            {                    
                ((dynamic) f).MyBindingFieldsList = bindingFieldsList;

                f.ShowDialog();
                            context.Instance.GetType().GetProperty("MyBindingFieldsCollection")?.SetValue(context.Instance, ((dynamic)f).MyBindingFieldsList); 
            }

        }
        else
        {
            using (var f = (Form)Activator.CreateInstance(editorFormInstance))
            {                   
                ((dynamic)f).MyBindingFieldsList = bindingFieldsList;

                f.ShowDialog();
     context.Instance.GetType().GetProperty("MyBindingFieldsCollection")?.SetValue(context.Instance, ((dynamic)f).MyBindingFieldsList);  

            }
        }
        return value; 
    }
}

MyBindingFields类:

public class MyBindingFields
{
    private ControlTypes _ControlType;
    public ControlTypes ControlType
    {
        get => _ControlType;
        set => _ControlType = value;
    }

    //public string MyParentEntity { get; set; }
    public string BindingField { get; set; }

    public string ChildEntity { get; set; }
    public string ValueMember { get; set; }
    public string DisplayMember { get; set; }
}

所以在设置值并按保存后会发生什么。 值存储在,当我点击再次打开此窗口时。我有我以前的记录,如果我添加一个新的记录它也很好。这里的问题是由于这个原因,数据没有序列化到designer.cs文件。当我运行程序或清理和重建解决方案时,我丢失了这些数据。 我在这里想念的是什么?当我按下保存按钮时,我需要做什么才能将数据序列化到designer.cs? enter image description here

1 个答案:

答案 0 :(得分:0)

要使用自定义编辑器对BindingList<MySampleModel>进行编辑,您需要应用以下更改:

1)该属性应由CollectionConverter

修饰
public partial class MyBaseForm<T> : Form
{
    public MyBaseForm()
    {
        InitializeComponent();
    }

    BindingList<MySampleModel> someProperty = new BindingList<MySampleModel>();
    [Editor(typeof(MyUITypeEditor), typeof(UITypeEditor))]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    [TypeConverter(typeof(CollectionConverter))]
    public BindingList<MySampleModel> SomeProperty
    {
        get { return someProperty; }
        set { someProperty = value; }
    }

    [Browsable(false)]
    public Type MyGenericType { get { return typeof(MySampleModel); } }
}

然后是DerivedForm

public partial class MyDerivedForm : MyBaseForm<MySampleModel>
{
    public MyDerivedForm()
    {
        InitializeComponent();
    }
}

注意:不需要YourModel标记为Serializer。您的模型将以这种方式序列化:

MCVE.MySampleModel mySampleModel1 = new MCVE.MySampleModel();
MCVE.MySampleModel mySampleModel2 = new MCVE.MySampleModel();
...
...
mySampleModel1.Id = 1;
mySampleModel1.Name = "X";
mySampleModel1.Price = 100;
mySampleModel2.Id = 2;
mySampleModel2.Name = "Y";
mySampleModel2.Price = 200;
this.SomeProperty.Add(mySampleModel1);
this.SomeProperty.Add(mySampleModel2);
...
...

2)MyEditorForm中,您应该在编辑后返回BindingList的新实例,以使设计器序列化列表:

public partial class MyEditorForm<T> : Form
{
    public MyEditorForm()
    {
        InitializeComponent();
        this.StartPosition = FormStartPosition.CenterScreen;
    }
    public BindingList<T> List
    {
        get
        {
            return (BindingList<T>)dataGridView1.DataSource;
        }
        set
        {
            if (value == null)
                value = new BindingList<T>();
            dataGridView1.DataSource = new BindingList<T>(value);
        }
    }
    private void button1_Click(object sender, EventArgs e)
    {
        this.DialogResult = DialogResult.OK;
    }
} 

3)在您的UITypeEditor中,您应该在对话框关闭后返回值:

public override object EditValue(ITypeDescriptorContext context,
    IServiceProvider provider, object value)
{
    var svc = provider.GetService(typeof(IWindowsFormsEditorService))
        as IWindowsFormsEditorService;
    var myGenericTypeProperty = context.Instance.GetType()
        .GetProperty("MyGenericType");
    var genericArgument = (Type)myGenericTypeProperty.GetValue(context.Instance);
    var editorFormType = typeof(MyEditorForm<>);
    var genericArguments = new[] { genericArgument };
    var editorFormInstance = editorFormType.MakeGenericType(genericArguments);
    if (svc != null) {
        using (var f = (Form)Activator.CreateInstance(editorFormInstance)) {
            f.GetType().GetProperty("List").SetValue(f, value);
            if (svc.ShowDialog(f) == DialogResult.OK)
                return ((dynamic)f).List;
        }
    }
    else {
        using (var f = (Form)Activator.CreateInstance(editorFormInstance)) {
            f.GetType().GetProperty("List").SetValue(f, value);
            if (f.ShowDialog() == DialogResult.OK)
                return ((dynamic)f).List;
        }
    }
    return base.EditValue(context, provider, value);
}