【问题标题】:Keep Control's default property from being included into Design-time serialisation保持 Control 的默认属性不包含在设计时序列化中
【发布时间】:2013-07-25 18:29:40
【问题描述】:

我有 UserControl,一半在 VS Designer 中创建,一半在代码中创建。 我想从代码中创建此 UserControl 的新实例,但每次都将其一些默认属性设置为不同的值。
示例(编辑真实代码):

// in my Main Form..
var newFrame = new RPictureFrame(); // my UserControl
newFrame.Width = 50;
newFrame.Height = 50;
newFrame.Location = new Point(0,0);
this.Controls.Add(newFrame);

newFrame = new RPictureFrame();
newFrame.Width = 200;
newFrame.Height = 400;
newFrame.Location = new Point(0,150);
this.Controls.Add(newFrame);

错误示例:

var newMyUserControl1 = new MyUserControl();  
newMyUserControl1.size.Width = 50;  

var newMyUserControl2 = new MyUserControl();  
newMyUserControl2.size.Width = 200;

有时会发生的情况是,我在创建新控件实例后立即设置的新值似乎被忽略了。
我唯一的解释是,由于我的 UserControl 是在 Designer 中设计的,因此它的所有默认属性实际上都序列化在 .resx 文件中(?)。当我在运行时创建新实例时,会在单独的线程中启动反序列化(我无法控制)。当我在反序列化之前意外设置了一些属性时,我的值会立即被 ser 的值覆盖。 我没有找到任何关于如何创建设计师创建的控件的信息,所以这当然只是我的猜测。

我的问题是,如何绕过它?可能是一些简单的方法。

我尝试过的事情:

1- 在我的 UserControl 代码中:

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Size size;

..从设计时序列化中删除标准属性。 但是(编译器说)我只是隐藏了现有的标准属性。 加上它当然不起作用。 我仍然是 c# 和 .NET 的初学者,所以也许我做错了?

2- 我想我可以订阅每个新控件的 (on)Load 事件,让它完全反序列化,然后设置我需要的内容。但它在代码中似乎非常繁琐,属性将不必要地设置两次(或更多)等。 基本上我不相信没有更优雅的解决方案:)

很高兴得到任何建议

【问题讨论】:

  • 您正落入一个标准的.NET 陷阱,每个程序员迟早都会落入该陷阱。您的“大小”属性返回值的副本。因为 Size 是一个值类型。分配 Width 属性只会更新该副本。多注意格伦的回答,他展示了正确的设置方法。
  • @Hans Passant 和 Glenn Cuevas:你们俩确实是对的。大小类型是一个结构,它的值不能像我在上面的例子中那样改变。 --尽管我写了,我的例子只是作为解释,并没有显示我的真实代码。我认为这不是一个好方法(下次注意:)。我已经编辑了 OP 示例以使其有意义。 - 我的问题仍然存在,因为问题仍然存在,如果我以正确的方式分配控件的属性(在新示例中)。 IE。我设置的属性值不会坚持。
  • 好吧,您发现在 SO 问题中发布虚假代码总是一个真的坏主意。贴出真实代码。
  • 你是对的。完成。--(抱歉,感谢您的耐心。这是我第一次使用 stackoverflow,所以我正在尝试最好的方式来解释事情。)
  • Generaly 你能告诉我我对对象反序列化的假设是否正确吗?

标签: c# winforms windows-forms-designer resx


【解决方案1】:

更新答案:

根据您的新代码:

newFrame.Width = 50;
newFrame.Height = 50;

将其更改为:

newFrame.Size = new Size(50, 50);

您会注意到该模式也被用于位置。

原答案:

当更改控件的大小时,您必须创建一个新的 Size 变量,因为它是一个值类型。

你的代码应该是:

newMyUserControl1.size = new Size(50, newMyUserControl1.size.Height);

查看此链接:

http://msdn.microsoft.com/en-us/library/system.windows.forms.control.size.aspx

【讨论】:

  • 我在 OP 中的示例只是解释我的方法的示例,而不是我的确切代码。无论如何,如果您查看它,您会发现我没有分配 Size(结构),只是 size.Width,一个 int。所以如果我没有错过任何东西,我的例子实际上是对的吗?无论如何,恐怕你的回答并不能解决我的问题。
  • 除非我遗漏了什么,否则您有一个名为 size 的公共成员,其类型为 Size。如果您查看我给您的链接,它有这样一段:“因为 Size 类是值类型,所以它是按值返回的,这意味着访问该属性会返回控件大小的副本。因此,调整 Width 或此属性返回的 Size 的 Height 属性不会影响控件的 Width 或 Height。要调整控件的 Width 或 Height,必须设置控件的 Width 或 Height 属性,或者将 Size 属性设置为新的 Size。 "
  • 对不起,我昨天累了,错过了你的意思。你确实是对的。大小类型是一个结构,它的值不能像我在上面的例子中那样改变。 --尽管我写了,我的例子只是作为解释,并没有显示我的真实代码。我认为这不是一个好方法(下次注意:)。我已经编辑了 OP 示例以使其有意义。 - 我的问题仍然存在,因为问题仍然存在,如果我以正确的方式分配控件的属性。 IE。我设置的属性值不会坚持。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-02
  • 2012-08-29
  • 1970-01-01
相关资源
最近更新 更多