简体   繁体   中英

Is it posible to set the order of the serialization of a custom property of a custom component/control in the designer-generated code?

I am working on some custom (inherited) controls with custom properties for which I have added design-time support after proper attribute decoration.

All works well but my problem is that the auto-generated code in the *.Designer.cs file where the control is used, has a particular order that it sets the various properties in (both base and new properties). This order looks like it is alphabetical wrt the property name.

So the auto generated code looks like this:

// 
// myTabPage1
// 
this.myTabPage1.Identifier = "ID";
this.myTabPage1.Name = "myTabPage1";
this.myTabPage1.Size = new System.Drawing.Size(294, 272);
this.myTabPage1.Text = "TTT";

Where I would have liked it to look like this:

// 
// myTabPage1
// 
this.myTabPage1.Name = "myTabPage1";
this.myTabPage1.Size = new System.Drawing.Size(294, 272);
this.myTabPage1.Text = "TTT";
this.myTabPage1.Identifier = "ID";

The reason I need this is because setting the Identifier property affects Text which is then reverted back to its design-time value, annulling the effect of setting the Identifier .

There are of course simple workarounds (the simplest of which is not to set the Text property which work well) but it would be nice if this was not a design-time "worry", as there is extensive usage of this design pattern in many inherited control types and their instances.

It is also helpful to set Text to identify the controls on the form designer ( Identifier has no effect on Text at design-time).

No, you can't affect serialization order. This is otherwise a common problem with a general solution, implement the ISupportInitialize interface . Your BeginInit() method is called just before the designer starts assigning properties, you'd typically set a bool variable that ensures that property setters don't have unintended side-effects. Your EndInit() method is called when it is done and all properties have a value, you'd set the variable back to false and do whatever you need to do to use the values.

Your question isn't specific enough about the control with the problem, but a possible implementation could look like this:

public partial class CustomControl : UserControl, ISupportInitialize {
    public CustomControl() {
        InitializeComponent();
    }
    private bool initializing;
    private string id = "";

    public string ID {
        get { return id; }
        set { id = value;
              if (!initializing) label1.Text = value;
        }
    }
    [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    public override string Text {
        get { return base.Text; }
        set {
            base.Text = value;
            if (!initializing && !this.DesignMode) label1.Text = value;
        }
    }

    public void BeginInit() {
        initializing = true;
    }

    public void EndInit() {
        initializing = false;
        label1.Text = ID;
    }
}

Also note the [DesignerSerializationVisibility] attribute in this code, when you use Hidden then the property doesn't get serialized at all. That could be a simple solution to your problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM