Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When a user control has Browsable false on public property, why does designer set it to null when added to a form?

I have a user control that has a few public properties, one is an object where I set [Browseable(false)]. When I add this control in Visual Studio's designer the generated code sets this object to null.

public class Foo : System.Windows.Forms.UserControl
{
    [Browsable(false)]
    public object Bar { get; set; }

    [Browsable(true)]
    public bool IsSomething { get; set; }

    ...
}

private void InitializeComponent()
{
    ...
    this.foo = new Foo();

    this.foo.IsSomething = false;
    this.foo.Bar = null;
    ...
}

I don't understand why Visual Studio would want to do that and I'm curious if there is a way to mark it so that it doesn't set it. I discovered this by setting the object to something in the constructor only to watch the contol's parent set it back to null.

like image 581
Jeff Avatar asked May 20 '09 18:05

Jeff


2 Answers

There are a couple of options here. First, BrowsableAttribute only determines whether the property shows up in the property grid. To prevent the property from being serialized at all, use the DesignerSerializationVisibilityAttribute:

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public object Bar { get; set; }

Second, if you want the property to be serialized, but only when the user has actually changed the value, use the DefaultValueAttribute:

[Browsable(true)]
[DefaultValue(false)]
public bool IsSomething { get; set; }

This will cause the property to only be serialized if it is different from its default value. This also has other positive side-effects

  1. The property value is shown in a normal font when it has not been changed, but in bold when it has been changed.
  2. The "Reset" option will be available when right-clicking the property in the property grid.

There are more advanced techniques for controlling property interaction with the designer (Google "ShouldSerialize"), but these attributes should get you most of the way there.

like image 178
David Nelson Avatar answered Nov 10 '22 11:11

David Nelson


Generally, when you set values in the constructor of your custom control, the VS designer will generate code that sets all those values that you're setting in the constructor. IE:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}

public class MyTextBox : TextBox
{
    public MyTextBox()
    {
        this.Person = new Person
        {
            FirstName = "John",
            LastName = "Doe",
            Age = 45
        };
    }


    [Browsable(false)]
    public Person Person { get; set; }
}

When I add a MyTextBox to my Form, this is the generated code:

// 
// myTextBox1
// 
this.myTextBox1.Location = new System.Drawing.Point(149, 91);
this.myTextBox1.Name = "myTextBox1";
person1.Age = 45;
person1.FirstName = "John";
person1.LastName = "Doe";
this.myTextBox1.Person = person1;
this.myTextBox1.Size = new System.Drawing.Size(100, 20);
this.myTextBox1.TabIndex = 3;

The catch here is though, that if you make changes to your constructor, you need to rebuild the project and in many cases remove the control from the form and re-add it so that VS can regenerate the code. I'm guessing that in your case VS just hasn't caught up to your changes. Try removing the control from the form and rebuilding the control. Then re-add it, and it should work.

like image 38
BFree Avatar answered Nov 10 '22 12:11

BFree