当用户控件在公共属性上具有Browsable false时,为什么设计者在添加到表单时将其设置为null?

时间:2021-01-15 20:12:44

I have a user control that has a few public properties, one is an object where I set [Browseable(false)]. When I add this control in Visual Studio's designer the generated code sets this object to null.

我有一个具有一些公共属性的用户控件,一个是我设置[Browseable(false)]的对象。当我在Visual Studio的设计器中添加此控件时,生成的代码将此对象设置为null。

public class Foo : System.Windows.Forms.UserControl
{
    [Browsable(false)]
    public object Bar { get; set; }

    [Browsable(true)]
    public bool IsSomething { get; set; }

    ...
}

private void InitializeComponent()
{
    ...
    this.foo = new Foo();

    this.foo.IsSomething = false;
    this.foo.Bar = null;
    ...
}

I don't understand why Visual Studio would want to do that and I'm curious if there is a way to mark it so that it doesn't set it. I discovered this by setting the object to something in the constructor only to watch the contol's parent set it back to null.

我不明白为什么Visual Studio会这样做,我很好奇是否有一种方法来标记它,以便它不设置它。我通过将对象设置为构造函数中的某些内容来发现这一点,只是为了观察控制器的父对象将其设置为null。

2 个解决方案

#1


There are a couple of options here. First, BrowsableAttribute only determines whether the property shows up in the property grid. To prevent the property from being serialized at all, use the DesignerSerializationVisibilityAttribute:

这里有几个选择。首先,BrowsableAttribute仅确定属性是否显示在属性网格中。要防止属性完全序列化,请使用DesignerSerializationVisibilityAttribute:

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public object Bar { get; set; }

Second, if you want the property to be serialized, but only when the user has actually changed the value, use the DefaultValueAttribute:

其次,如果您希望序列化属性,但仅当用户实际更改了值时,请使用DefaultValueAttribute:

[Browsable(true)]
[DefaultValue(false)]
public bool IsSomething { get; set; }

This will cause the property to only be serialized if it is different from its default value. This also has other positive side-effects

这将导致属性仅在与其默认值不同时才被序列化。这也有其他积极的副作用

  1. The property value is shown in a normal font when it has not been changed, but in bold when it has been changed.
  2. 属性值在未更改时以正常字体显示,但在更改后以粗体显示。

  3. The "Reset" option will be available when right-clicking the property in the property grid.
  4. 右键单击属性网格中的属性时,“重置”选项将可用。

There are more advanced techniques for controlling property interaction with the designer (Google "ShouldSerialize"), but these attributes should get you most of the way there.

有更多先进的技术可以控制与设计师的交互(Google“ShouldSerialize”),但这些属性应该可以帮助你完成大部分工作。

#2


Generally, when you set values in the constructor of your custom control, the VS designer will generate code that sets all those values that you're setting in the constructor. IE:

通常,当您在自定义控件的构造函数中设置值时,VS设计器将生成代码,用于设置您在构造函数中设置的所有值。 IE:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}

public class MyTextBox : TextBox
{
    public MyTextBox()
    {
        this.Person = new Person
        {
            FirstName = "John",
            LastName = "Doe",
            Age = 45
        };
    }


    [Browsable(false)]
    public Person Person { get; set; }
}

When I add a MyTextBox to my Form, this is the generated code:

当我将MyTextBox添加到我的表单时,这是生成的代码:

// 
// myTextBox1
// 
this.myTextBox1.Location = new System.Drawing.Point(149, 91);
this.myTextBox1.Name = "myTextBox1";
person1.Age = 45;
person1.FirstName = "John";
person1.LastName = "Doe";
this.myTextBox1.Person = person1;
this.myTextBox1.Size = new System.Drawing.Size(100, 20);
this.myTextBox1.TabIndex = 3;

The catch here is though, that if you make changes to your constructor, you need to rebuild the project and in many cases remove the control from the form and re-add it so that VS can regenerate the code. I'm guessing that in your case VS just hasn't caught up to your changes. Try removing the control from the form and rebuilding the control. Then re-add it, and it should work.

但是,如果您对构造函数进行更改,则需要重新构建项目,并且在许多情况下从表单中删除控件并重新添加它,以便VS可以重新生成代码。我猜你的情况就是VS还没有赶上你的改变。尝试从窗体中删除控件并重新生成控件。然后重新添加它,它应该工作。

#1


There are a couple of options here. First, BrowsableAttribute only determines whether the property shows up in the property grid. To prevent the property from being serialized at all, use the DesignerSerializationVisibilityAttribute:

这里有几个选择。首先,BrowsableAttribute仅确定属性是否显示在属性网格中。要防止属性完全序列化,请使用DesignerSerializationVisibilityAttribute:

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public object Bar { get; set; }

Second, if you want the property to be serialized, but only when the user has actually changed the value, use the DefaultValueAttribute:

其次,如果您希望序列化属性,但仅当用户实际更改了值时,请使用DefaultValueAttribute:

[Browsable(true)]
[DefaultValue(false)]
public bool IsSomething { get; set; }

This will cause the property to only be serialized if it is different from its default value. This also has other positive side-effects

这将导致属性仅在与其默认值不同时才被序列化。这也有其他积极的副作用

  1. The property value is shown in a normal font when it has not been changed, but in bold when it has been changed.
  2. 属性值在未更改时以正常字体显示,但在更改后以粗体显示。

  3. The "Reset" option will be available when right-clicking the property in the property grid.
  4. 右键单击属性网格中的属性时,“重置”选项将可用。

There are more advanced techniques for controlling property interaction with the designer (Google "ShouldSerialize"), but these attributes should get you most of the way there.

有更多先进的技术可以控制与设计师的交互(Google“ShouldSerialize”),但这些属性应该可以帮助你完成大部分工作。

#2


Generally, when you set values in the constructor of your custom control, the VS designer will generate code that sets all those values that you're setting in the constructor. IE:

通常,当您在自定义控件的构造函数中设置值时,VS设计器将生成代码,用于设置您在构造函数中设置的所有值。 IE:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}

public class MyTextBox : TextBox
{
    public MyTextBox()
    {
        this.Person = new Person
        {
            FirstName = "John",
            LastName = "Doe",
            Age = 45
        };
    }


    [Browsable(false)]
    public Person Person { get; set; }
}

When I add a MyTextBox to my Form, this is the generated code:

当我将MyTextBox添加到我的表单时,这是生成的代码:

// 
// myTextBox1
// 
this.myTextBox1.Location = new System.Drawing.Point(149, 91);
this.myTextBox1.Name = "myTextBox1";
person1.Age = 45;
person1.FirstName = "John";
person1.LastName = "Doe";
this.myTextBox1.Person = person1;
this.myTextBox1.Size = new System.Drawing.Size(100, 20);
this.myTextBox1.TabIndex = 3;

The catch here is though, that if you make changes to your constructor, you need to rebuild the project and in many cases remove the control from the form and re-add it so that VS can regenerate the code. I'm guessing that in your case VS just hasn't caught up to your changes. Try removing the control from the form and rebuilding the control. Then re-add it, and it should work.

但是,如果您对构造函数进行更改,则需要重新构建项目,并且在许多情况下从表单中删除控件并重新添加它,以便VS可以重新生成代码。我猜你的情况就是VS还没有赶上你的改变。尝试从窗体中删除控件并重新生成控件。然后重新添加它,它应该工作。