【问题标题】:User Control custom properties lose state when user control is rebuilt重建用户控件时,用户控件自定义属性会丢失状态
【发布时间】:2011-04-13 04:20:32
【问题描述】:

我有一个具有如下自定义属性的用户控件:

[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;
    }
}

该控件包含一个标准按钮控件。该属性用于显示或隐藏按钮。用户控件内置在单独的项目程序集中。我把它放在一个表单上,我可以设置和取消设置上面的属性,一切看起来都很好。但是,当重建包含用户控件的项目时,属性值会翻转为“false”,这不是默认值。

如何防止自定义属性在控件重建时丢失/更改其状态?

【问题讨论】:

    标签: c# winforms user-controls properties custom-controls


    【解决方案1】:

    问题在于DefaultValueAttribute 只告诉设计者该属性的默认值是什么。它控制该属性是否以粗体显示,以及当您右键单击该属性并从上下文菜单中选择“重置”时该值被重置为什么。

    做的是在运行时将属性设置为特定值。为此,您需要在用户控件的构造方法中放置代码。例如:

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

    否则,正如您所描述的,当您重建项目时,该属性的值将被重置。它将在设计器的“属性”窗口中以 粗体 显示,因为它与默认值不匹配(在 DefaultValueAttribute 中指定),但该属性不会更改值是什么设置为。

    【讨论】:

    • 我尝试了上述方法并在用户控件的构造函数中设置了“this.removeButton.Visible = true”。最初它似乎保持其状态。未更改的重建不会更改属性值。但是,当我对用户控件进行更改并重建它时,该属性再次切换为“false”并变为粗体。这很烦人。
    • @Elan:那么你的代码中肯定有一些东西在改变值。我创建了许多可重用的控件库和用户控件,但我从来没有遇到过这个问题。在您的代码中进行搜索,看看您是否在任何地方设置了 removeButton.Visible 属性。它可能隐藏在自动插入的*.Designer.cs 文件中,您看不到它。
    • 用户控件在构造函数中将属性设置为“true”。主窗体的designer.cs 是生成“ShowRemoveButton”属性为false 的代码。只有这两个地方。我删除了用户控件属性声明上的 [DefaultValue(true)] 属性,希望将主窗体上的属性设置为“true”会导致值保持不变。然而,当重新生成 Designer.cs 类并替换为“false”时,“true”的属性值会丢失。我无法坚持“真正”的价值。这发生在某些表单设计器更改和重建之后。
    • @Elan:如果您可以可靠地复制此内容,请考虑编辑您的问题以包含其他人这样做所需的最少代码。我想我明白你在说什么,但我以前从未在自己的使用中看到过这种行为。我知道在某些极端情况下,Visual Studio 的设计器会搞砸事情,但我有兴趣尽可能多地调查这些情况。如果我可以自己重现它,我可以为您提供修复,或者向 Microsoft 提交错误报告并在此处链接到它以供其他人确认。
    • 谢谢,我将尝试隔离重现所需的最少代码量并将其发布。我需要几天时间才能回复您。
    【解决方案2】:

    防止任何包含的控件的属性在相关属性的(反)序列化时被重置的一种简单方法是使用属性的私有支持字段并分配与DefaultValue属性参数匹配的默认值。在这种情况下,这就是下面的 _showRemoveButton = true 声明/赋值。

    [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;
    

    【讨论】:

      【解决方案3】:

      旧帖子,但它引导我找到解决问题的方法。我得到了完全一样的效果,我的财产在重建时丢失了。在我的例子中,该属性本身就是一个类,它提供了一堆布尔值。

      对我来说,解决方案是改变设计人员对属性进行序列化的方式。

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

      通过使用 DesignerSerializationVisibility.Content,您可以告诉设计器序列化属性类的内容(我的布尔值包含在 SomePropertyClass 中)而不是属性本身。我想另一种方法是使 SomePropertyClass 可序列化,但上述方法实现起来更快。

      也许这对某人有帮助。 萨沙

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-02-12
        • 1970-01-01
        • 2012-02-18
        • 1970-01-01
        • 2010-12-27
        • 1970-01-01
        相关资源
        最近更新 更多