Properties won't get serialized into the .desi

2019-02-19 02:06发布

In VS2010, control properties won't get serialized despite the ShouldSerializeFoo method, with the DesignerSerializationVisibility.Visible/Content as well.

Here's the code:

class Class1 : UserControl {
    [Browsable(true)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public string Foo {
        get; set;
    }
    public bool ShouldSerializeFoo() {
        return true;
    }
    public Class1() {
        Foo = "dupa";
    }
}

However, the designer doesn't generate anything for this property:

        // 
        // class11
        // 
        this.class11.Location = new System.Drawing.Point(224, 262);
        this.class11.Name = "class11";
        this.class11.Size = new System.Drawing.Size(150, 150);
        this.class11.TabIndex = 2;
        this.class11.Load += new System.EventHandler(this.class11_Load);

1条回答
可以哭但决不认输i
2楼-- · 2019-02-19 02:49

You're mixing serialization schemes. The designer serialization (which is what DesignerSerializationVisibility is for) has nothing to do with the instance serialization mechanism (which is what ShouldSerializeXXX functions, among many other things, deal with).

DesignerSerializationVisibility.Content doesn't make much sense for a string (or any other immutable type). The designer can view a property's serialization as three types:

  • None - it never serializes anything about the property
  • Visible - it will serialize the actual value of the property
  • Content - it will serialize the property values of the value of the property.

By default, a property is considered Visible. I realize that my definition of Content might be a little confusing. What I mean by that is like this:

public class MyControl : Control
{
    public class SomeOptions
    {
        public string Option1 { get; set; }
        public string Option2 { get; set; }
    }

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public SomeOptions Options { get; private set; }

    public string Foo { get; set; }
}

Now, when this class is serialized by the designer, it will look something like this:

// myControl1
this.myControl1.Foo = "value";
this.myControl1.Options.Option1 = "option1";
this.myControl1.Options.Option2 = "option2";

This should hopefully make more sense; marking a property as Content signifies that, rather than serializing the actual value of the property (in this case, it would be an instance of SomeOptions), it should serialize the property values of that value instead.

So, back to your question, that's why you don't want Content for a string property. Because strings are immutable, there's nothing for the designer to serialize. Either mark it as Visible or leave the attribute off entirely (since that's the default).

While it's possible to provide custom direction to the designer as to whether or not you want to serialize a particular property, it's a pretty involved (and nasty) process. The easy way, though, is to use the DefaultValue attribute on the property. If whether or not the property should be serialized can be determined by comparing its value to a constant (in other words, it's not dependent upon anything else at runtime, like the value of another property), you can decorate the property like this:

[DefaultValue("foo")]
public string Foo { get; set; }

If the designer then sees that the value of Foo is equal to "foo", then it won't serialize the property at all.

查看更多
登录 后发表回答