当用户控件被重建时,用户控件的自定义属性会丢失状态。

4

我有一个用户控件,其中包含以下自定义属性:

[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”,这不是默认值。

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

3个回答

5
问题在于 DefaultValueAttribute 只告诉了设计者该属性的默认值是什么。它控制了该属性是否以粗体显示,并且当您右键单击属性并从上下文菜单中选择“重置”时,它会将值重置为什么。
但是它 不会 在运行时将属性设置为特定的值。要做到这一点,您需要在用户控件的构造函数中放置代码。例如:
// set default visibility
this.removeButton.Visible = true;

否则,就像您所描述的那样,在重新构建项目时属性值将被重置。在设计器的属性窗口中,它将以粗体显示,因为它与默认值(如DefaultValueAttribute中指定的)不匹配,但该属性不会改变属性的值。

我尝试了上述方法,并在用户控件的构造函数中设置了“this.removeButton.Visible = true”。最初它似乎保持了其状态。没有更改的重建不会改变属性值。然而,当我对用户控件进行更改并重新构建时,该属性再次切换为“false”并变为粗体。这非常令人恼火。 - Elan
@Elan:那么你的代码中肯定有某些东西在改变这个值。我已经创建了许多可重用的控件库和用户控件,但从来没有遇到过这样的问题。在你的代码中搜索一下,看看是否有任何设置removeButton.Visible属性的地方。它可能隐藏在自动插入的"*.Designer.cs"文件中,而你无法看到它。 - Cody Gray
用户控件在构造函数中将属性设置为“true”。主窗体的designer.cs代码生成“ShowRemoveButton”属性为false。这些是唯一的两个地方。我删除了用户控件属性声明上的[DefaultValue(true)]属性,希望在主窗体上将属性设置为“true”会使值保持不变。然而,在重新生成designer.cs类并替换后,“true”的属性值会丢失,并被替换为“false”。我无法让“true”值保持不变。这发生在一些表单设计更改和重建之后。 - Elan
@Elan:如果您能够可靠地重现此问题,请考虑编辑您的问题以包括其他人所需的最小代码。我认为我理解了你的意思,但我在自己的使用中从未见过这种行为。我知道有一些边缘情况,Visual Studio的设计师会搞砸一些东西,但我有兴趣调查尽可能多的情况。如果我可以自己重现它,我可以为您提供修复或向Microsoft提交错误报告并在此处链接以供其他人确认。 - Cody Gray
谢谢,我会尝试隔离最少量的代码以便复现,并会发布它。我需要几天时间来回复您。 - Elan

3
一个简单的方法来防止任何包含控件属性在相关属性的(反)序列化时被重置,就是使用一个私有的后备字段来存储属性,并且赋一个与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;

1

虽然这篇文章有些老,但它帮助我解决了我的问题。我遇到了和作者一样的问题,即在重建后我的属性状态丢失了。在我的情况下,该属性是一个类本身,提供了一堆布尔值。

对我来说,解决方案是改变设计者序列化属性的行为。

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

通过使用DesignerSerializationVisibility.Content,您告诉设计师序列化属性类的内容(包含在SomePropertyClass中的布尔值),而不是属性本身。我猜另一种方法是使SomePropertyClass可序列化,但上述方法更快实现。 也许这能帮助某些人。 Sascha

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接