以基本形式定义的自定义属性在重建时会以继承的形式丢失其状态

Ela*_*lan 5 c# inheritance designer properties winforms

我遇到基本形式的属性无法以继承形式维护状态的问题.

环境:

  • Visual Studio 2010 Ultimate Service Pack 1:版本10.0.40219.1 SP1Rel
  • .Net Framework:版本4.0.30319 SP1Rel
  • Windows 7旗舰版

下面是重现的源代码和步骤:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在上面,默认属性与[DefaultValueAttribute]匹配,即在InitializeComponent()中,checkBox1.Visible设置为true,checkBox1.Checked为false.这些是放在表单上时控件的默认设置.

然后我创建了以下继承的表单:

using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace Test
{
    public partial class Form1 : BaseForm
    {
        public Form1()
        {
            InitializeComponent();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

问题和重现步骤:

  1. 当我在设计器中打开Form1时,属性处于以下状态.

    状态:ControlChecked = False - ControlVisible = True(粗体)

    ControlVisible按预期设置为True,但它是粗体.[DefaultValueAttribute] 在基本表单中设置为true,因此我希望此属性不以粗体显示.

  2. 我现在在设计器中将ControlVisible更改为False.大胆的关闭.

    状态:ControlChecked = False - ControlVisible = False

  3. 我现在重建项目并重新生成Form1中的代码.该ControlVisible属性恢复为粗体.

    状态:ControlChecked = False - ControlVisible = True(粗体)

  4. 我现在将ControlCheckedFalse更改为True,并按预期变为粗体.

    状态:ControlChecked = True(粗体) - ControlVisible = True(粗体)

  5. 我重建项目并没有改变.

    状态:ControlChecked = True(粗体) - ControlVisible = True(粗体)

  6. 我现在将ControlVisible的属性从True更改为False并再次重建项目.ControlVisible以粗体显示回到True.

    状态:ControlChecked = True(粗体) - ControlVisible = True(粗体)

ControlChecked似乎按预期工作.ControlVisible不断翻转回当它被设置为false,大胆的反转.在我看来,无法识别基本形式中的[DefaultAttributeValue]为true.

更新: 修改以修复错误,更准确地隔离问题.

更新: 如果我在BaseForm的构造函数中设置checkBox1.Visible = false,那么一切都按预期工作.因此,最重要的是,似乎问题是在继承的表单中的自定义属性上识别为DefaultValueAttribute为true.

Bor*_* B. 2

你的私人是checkBox1基类吗?如果不是,那就应该是,因为设计器将序列化两个 setter(一个用于 checkBox1.Visible,另一个用于 ControlVisible),并且只有序列化的顺序才能确定最终状态,这是不好的。

另外,查看 Form1.designer.cs 文件中自动生成的 InitializeControls 方法,它是否显式将自定义属性设置为默认值?

最后,尝试使用ShouldSerialze 和 Reset并查看是否会得到不同的行为。

编辑

我在本地重新创建了该问题,并附加了一个 VS 实例来调试另一个实例。VS第一次ControlVisible评估该属性时,它返回,false因为checkBox1.Visible(获取器源)是false. 当创建并显示实际的复选框控件,并且滚动“属性”窗口以显示ControlVisible它的值时,它会再次计算并返回true,这是默认值,但是 VS 内部似乎已经将该属性标记为已修改,因为它是初始值与默认值不同。这可能是VS的一个bug。

我创建了一个简单的效果演示:

    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);
    }
}
Run Code Online (Sandbox Code Playgroud)

当继承上述内容时,BaseFormTestPropery行为与您的示例中的完全相同ControlVisible,所以我认为这是 VS 中的一个错误。

问题的解决方案是使用简单的布尔支持字段作为帮助器,因为 checkBox1.Visible 不可靠:

    public BaseForm()
    {
        InitializeComponent();
        checkBox1.Visible = _controlVisible = true;
    }

    private bool _controlVisible;

    [DefaultValue(true)]
    public bool ControlVisible
    {
        get { return _controlVisible; }
        set { _controlVisible = checkBox1.Visible = value; }
    }
Run Code Online (Sandbox Code Playgroud)