2017-11-10 4 views
0

안녕하세요 저는 양식과 함께 사용자 정의 genric 양식, 사용자 정의 유형 및 UITypeEditor를 보유하고 있습니다.Serializing 디자인시 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 클래스 : 내가 값을 설정하고 Enter 키를 저장 한 후

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로 데이터가 serialize됩니다. DerivedForm에 대한 다음

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); } } 
} 

:

1) 속성은 CollectionConverter 장식한다 : enter image description here

+0

public 속성에 의해 데이터가 노출되고 유형에 [Serializable] 특성이있는 경우에만 데이터를 InitializeComponent()로 serialize 할 수 있습니다. 이 일을 지나치게 지키지 마십시오. 위험합니다. 형식을 변경할 때 얻을 수있는 종류와 같은 디자인 타임의 예외는 매우 불쾌한 문제를 일으 킵니다. InitializeComponent()는 아주 좋은 데이터베이스가 아닙니다. –

+0

나는 문자열 값만 여기에 저장하고있다. 심지어 MyBindingFields 클래스 위에 serializable 특성을 넣으면 여전히 작업을 수행하지 않는다. 그래서 어떤 제안? – Licentia

+0

여기에서 문제는'Serializable' 속성이 아닙니다. 실제로 모델을 직렬화 가능으로 표시 할 필요는 없습니다. 대신에, 당신은 'CollectionConverter'을 속성의 형식 변환기로 사용해야합니다. 또한 현재 코드에서 편집자는 편집 된 값을 반환하지 않습니다. 'ShowDialog' 다음에 대화 상자에서 얻은 값을 반환해야합니다. 코드를 작동 시키려면 두 가지 변경 사항을 적용해야합니다. –

답변

0

, 당신은 이러한 변경 사항을 적용 할 필요가 사용자 정의 편집기를 사용하여 BindingList<MySampleModel>을 편집 할 수있게하려면 :

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

참고 :YourModelSerializer으로 표시 할 필요가 없습니다. MyEditorForm에서

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), 당신은 편집 후 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); 
} 
+0

코드 샘플을 사용하여 솔루션을 테스트했으며 올바르게 작동합니다. 내 코드 예제와 코드 사이에 약간의 차이점이 있습니다. 코드 차이는 전체 답변에서 변경되지 않습니다. 솔루션을 적용하는 데 문제가 있으면 알려주십시오. –

+0

답변에 대한 질문이 있으면 알려주세요 ... –