【问题标题】:Derived collection property not serialized in designer未在设计器中序列化的派生集合属性
【发布时间】:2018-11-07 09:05:01
【问题描述】:

我的类派生自具有 MyString 属性的集合,即

  public class CollectionItem
  {
    public bool MyBoolean { get; set; }

    public int MyInteger { get; set; }
  }

  public class MyCollection : List<CollectionItem>
  {
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    public string MyString { get; set; }

    public MyCollection()
    {
      MyString = "Hello";
    }
  }

这个集合是一个简单的 DummyControl 的一部分,即

  public class DummyControl : System.Windows.Forms.Control
  {
    protected override void OnPaint(PaintEventArgs e)
    {
      base.OnPaint(e);
      e.Graphics.FillRectangle(System.Drawing.Brushes.Yellow, e.ClipRectangle);
    }

    public DummyControl() 
    {
      MyCollection = new MyCollection();

      for (int i = 0; i < 3; i++)
      {
        CollectionItem item = new CollectionItem();
        item.MyInteger = i;
        item.MyBoolean = i > 1;
        MyCollection.Add(item);
      }
    }

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public MyCollection MyCollection { get; set; }
  }

当我将此 DummyControl 放在 Windows 窗体上时,除了 MyString 属性之外,所有内容都按预期对窗体设计器进行序列化 - 这就是我得到的:

  // 
  // dummyControl1
  // 
  this.dummyControl1.Location = new System.Drawing.Point(66, 62);
  collectionItem1.MyBoolean = false;
  collectionItem1.MyInteger = 0;
  collectionItem2.MyBoolean = false;
  collectionItem2.MyInteger = 1;
  collectionItem3.MyBoolean = true;
  collectionItem3.MyInteger = 2;
  this.dummyControl1.MyCollection.Add(collectionItem1);
  this.dummyControl1.MyCollection.Add(collectionItem2);
  this.dummyControl1.MyCollection.Add(collectionItem3);
  this.dummyControl1.Name = "dummyControl1";
  this.dummyControl1.Size = new System.Drawing.Size(338, 266);
  this.dummyControl1.TabIndex = 0;
  this.dummyControl1.Text = "dummyControl1";

谁能告诉我我还需要做什么才能将 MyString 属性序列化到表单设计器?

【问题讨论】:

    标签: c# .net winforms windows-forms-designer


    【解决方案1】:

    默认 CodeDom 集合序列化程序不会序列化集合的属性。您可以通过从CodeDomSerializer 派生来创建自定义序列化程序。然后为您的类注册自定义序列化程序:

    [DesignerSerializer(typeof(MyCollectionSerializer), typeof(CodeDomSerializer))]
    public class MyCollection : List<CollectionItem>
    

    MyCollectionSerializer

    此序列化程序序列化MyCollectionMyString 属性:

    using System.CodeDom;
    using System.ComponentModel;
    using System.ComponentModel.Design.Serialization;
    public class MyCollectionSerializer : CodeDomSerializer
    {
        public override object Serialize(IDesignerSerializationManager manager, object value)
        {
            var baseSerializer = (CodeDomSerializer)manager.GetSerializer(
                typeof(MyCollection).BaseType, typeof(CodeDomSerializer));
            var statements = (CodeStatementCollection)baseSerializer.Serialize(manager, value);
            var property = TypeDescriptor.GetProperties(value)[nameof(MyCollection.MyString)];
            if (property.ShouldSerializeValue(value))
            {
                var targetObject = base.GetExpression(manager, value);
                var cpre = new CodePropertyReferenceExpression(targetObject, property.Name);
                var cpe = new CodePrimitiveExpression(property.GetValue(value));
                var cas = new CodeAssignStatement(cpre, cpe);
                statements.Add(cas);
            }
            return statements;
        }
    } 
    

    那么MyString属性也会被序列化:

    // 
    // dummyControl1
    // 
    ...
    this.dummyControl1.MyCollection.Add(collectionItem1);
    this.dummyControl1.MyCollection.Add(collectionItem2);
    this.dummyControl1.MyCollection.Add(collectionItem3);
    this.dummyControl1.MyCollection.MyString = "Hello";
    ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-31
      • 1970-01-01
      • 1970-01-01
      • 2013-03-03
      相关资源
      最近更新 更多