4

I have a user control with custom properties as follows:

[DefaultValue(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Description("Gets or sets whether the \"Remove\" button is visible.")]
public bool ShowRemoveButton
{
    get
    {
        return this.removeButton.Visible;
    }
    set
    {
        this.removeButton.Visible = value;
    }
}

The control contains a standard button control. This property is used to show or hide the button. The user control is built in a separate project assembly. I placed it on a form and I can set and unset the above property and everything appears to be working just fine. However, when the project containing the user control is rebuilt, the property value flips to "false", which is not the default.

How can I prevent the custom property from losing/altering its state when the control is rebuilt?

Elan
  • 6,084
  • 12
  • 64
  • 84

3 Answers3

5

The problem is that the DefaultValueAttribute only tells the designer what the default value is for the property. It controls whether the property is displayed in bold, and what the value gets reset to when you right-click on the property and choose "Reset" from the context menu.

What it doesn't do is set the property to a particular value at run-time. To do that, you'll need to place code in your user control's constructor method. For example:

// set default visibility
this.removeButton.Visible = true;

Otherwise, as you've described, the value of the property will be reset when you rebuild the project. It will show up in bold in the Properties window of the designer, because it doesn't match the default (as specified in the DefaultValueAttribute), but that attribute doesn't change what the value is set to.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • I tried the above and set "this.removeButton.Visible = true" in the user control's constructor. Initially it appeared to keep its state. Rebuilds without changes did not change the property value. However, when I made a change to the user control and rebuilt it, again the property switched to "false" and became bold. This is quite annoying. – Elan Apr 13 '11 at 15:01
  • @Elan: Then there has to be something in your code that's changing the value. I've created a number of reusable control libraries and user controls, but I've never had a problem with this. Do a search in your code to see if you have anywhere setting the `removeButton.Visible` property. It's likely hidden in the `*.Designer.cs` file where it was automatically inserted and you can't see it. – Cody Gray - on strike Apr 14 '11 at 05:00
  • The user control sets property to "true" in constructor. The designer.cs of the main form is code generating "ShowRemoveButton" property to false. Those are the only two places. I removed the [DefaultValue(true)] attribute on the property declaration on the user control in the hopes that setting the property on the main form to "true" would cause the value to stick. Yet, the property value of "true" is lost when the designer.cs class is regenerated and is replaced with "false". I cannot get the "true" value to stick. This occurs after some form designer changes and rebuilding. – Elan Apr 14 '11 at 16:12
  • @Elan: If you can reliably reproduce this, please consider editing your question to include the minimum code required for others to do so. I think I understand what you're saying, but I haven't seen this behavior before in my own use. I know there are some edge cases where Visual Studio's Designer will bork things up, but I'm interested in investigating as many of those as possible. If I can reproduce it myself, I can either get you a fix, or get a bug report filed with Microsoft and link to it here for others to confirm. – Cody Gray - on strike Apr 14 '11 at 23:32
  • Thanks, I will attempt to isolate the minimum amount of code required to reproduce and will post it. I will need a couple of days to get back to you on this. – Elan Apr 15 '11 at 13:37
3

An easy way to keep any contained controls' properties from being reset upon (de)serialization of related properties is to use a private backing field for the property and assign a default value that matches the DefaultValue attribute's parameter. In this case, that's the _showRemoveButton = true declaration/assignment below.

[DefaultValue(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Description("Gets or sets whether the \"Remove\" button is visible.")]
public bool ShowRemoveButton
{
    get
    {
        return _showRemoveButton;
    }
    set
    {
        _showRemoveButton = value;
        this.removeButton.Visible = value;
    }
}
private bool _showRemoveButton = true;
1

Old post but it guided me to the solution for my problem. I had excatly the same effect, that the state of my property was lost upon rebuild. In my case the property is a class itself, that provides a bunch of Booleans.

For me the solution was to change the bevhaviour how the designers serlializes the property.

   [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public SomePropertyClass SomeProperty
{
    get { return _SomeProperty; }
    set { _SomeProperty = Value; }
}

By using DesignerSerializationVisibility.Content you tell the designer to serialize the content of the property class (my Boolean contained in SomePropertyClass) rather than the property itself. I guess another approach would be to make SomePropertyClass serializable, but the above approach was quicker to implement.

Maybe that helps somebody. Sascha

Sascha
  • 1,210
  • 1
  • 17
  • 33