Custom properties defined in base form lose their state in inherited form upon rebuild
I am having trouble with properties of a base form not maintaining state in an inherited form.
Environment:
- Visual Studio 2010 Ultimate Service Pack 1: Version 10.0.40219.1 SP1Rel
- .Net Framework: Version 4.0.30319 SP1Rel
- Windows 7 Ultimate
Below, is the source code and steps to reproduce:
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace Test
{
public partial class BaseForm : Form
{
[DefaultValueAttribute(true)]
public bool ControlVisible
{
get
{
return this.checkBox1.Visible;
}
set
{
this.checkBox1.Visible = value;
}
}
[DefaultValueAttribute(false)]
public bool ControlChecked
{
get
{
return this.checkBox1.Checked;
}
set
{
this.checkBox1.Checked = value;
}
}
public BaseForm()
{
InitializeComponent();
}
}
}
In the above the default properties match up with the [DefaultValueAttribute], i.e. in InitializeComponent() checkBox1.Visible is set to true and checkBox1.Checked is false. T开发者_如何转开发hese are the default settings for the control when dropped onto the form.
I then created the following inherited form:
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace Test
{
public partial class Form1 : BaseForm
{
public Form1()
{
InitializeComponent();
}
}
}
Issue and steps to reproduce:
When I open Form1 in the designer the properties are the in following state.
State: ControlChecked = False - ControlVisible = True (bold)
ControlVisible is set to True as expected, however it is bold. The [DefaultValueAttribute] is set to true in the base form, so I would have expected this property to not be in bold.
I now change ControlVisible to False in the designer. The bold turns off.
State: ControlChecked = False - ControlVisible = False
I now rebuild the project and the code in Form1 gets regenerated. The ControlVisible property reverts back to True in bold.
State: ControlChecked = False - ControlVisible = True (bold)
I now change ControlChecked from False to True and it becomes bold as expected.
State: ControlChecked = True (bold) - ControlVisible = True (bold)
I rebuild the project and no change.
State: ControlChecked = True (bold) - ControlVisible = True (bold)
I now change the property of ControlVisible from True to False and rebuild the project again. ControlVisible flipped back to True in bold.
State: ControlChecked = True (bold) - ControlVisible = True (bold)
ControlChecked appears to be working as expected. ControlVisible keeps flipping back to True when it is set to false and the bold is reversed. Seems to me that somehow the [DefaultAttributeValue] of true in the base form is not recognized.
Update: Revised to fix a bug and more exactly isolate the issue.
Update: If I set checkBox1.Visible = false in the constructor of BaseForm, then everything works as expected. So, bottom line it appears that the trouble is getting the DefaultValueAttribute of true to be recognized on the custom property in the inherited form.
Your ControlVisible property always gets set to false:
[DefaultValueAttribute(true)]
public bool ControlVisible
{
get
{
return this.checkBox1.Visible;
}
set
{
this.checkBox1.Visible = false;
}
}
Your set method should be:
this.checkBox1.Visible = value;
Is your checkBox1
private in the base class? If it's not then it should be, because the designer will serialize both setters (one for checkBox1.Visible and the other for ControlVisible), and only the order of serialization will determine the final state, which is bad.
Also, look at the autogenerated InitializeControls method in the Form1.designer.cs file, does it explicitly set the custom properties to default values?
Finally, try using ShouldSerialze and Reset and see if you get different behavior.
Edit
I've recreated the problem locally and attached one VS instance to debug another. The first time the property ControlVisible
was evaluated by VS it returned false
because checkBox1.Visible
(the getter source) was false
. When the actual checkbox control was created and shown, and the Properties window was scrolled to display ControlVisible
it's value was evaluated again and it returned true which is the default value, however it seems that VS internally already tagged that propery as modified, since it's initial value was different than the default. This may be a bug in VS.
I've created a simple demonstration of the effect:
public BaseForm()
{
InitializeComponent();
_testValue = false;
}
private bool _testValue;
[DefaultValue(true)]
public bool TestProperty
{
get { return _testValue; }
set { _testValue = value; }
}
protected override void OnVisibleChanged(EventArgs e)
{
_testValue = true;
base.OnVisibleChanged(e);
}
}
When inheriting the above BaseForm
the TestPropery
behaves exactly like the ControlVisible
in your example, so I think it's a bug in VS.
The solution to your problem is to use a simple bool backing field as a helper, because checkBox1.Visible is unreliable:
public BaseForm()
{
InitializeComponent();
checkBox1.Visible = _controlVisible = true;
}
private bool _controlVisible;
[DefaultValue(true)]
public bool ControlVisible
{
get { return _controlVisible; }
set { _controlVisible = checkBox1.Visible = value; }
}
精彩评论