控件、窗体的构造方法和加载方法的比较
因为窗体Form也是从Control类继承而来,所以实质上窗体也是一种控件。为了方便叙述,下面都只提到窗体,但是下面讲的内容对窗体和控件都适用。
窗体的构造方法和加载方法一般是进行一些初始化处理的地方,如在窗体构造方法中就有这么一个方法InitializeComponent(),这个方法就是对窗体中的子控件进行初始化工作的,比如所有子控件的创建、指定大小位置等属性等等。而窗体加载方法protected override OnLoad()是在窗体显示之前,对窗体作的最后一步初始化工作。
比较:
(1)两者都是用于对窗体进行一些初始化工作。
(2)两者的执行顺序不同。构造方法要先于加载方法执行,当我们利用new生成一个新窗体对象时,首先执行的
是窗体的构造方法。然而并不是接下来就会去执行加载方法,窗体加载方法只有等到窗体将要显示的时候也
即调用Show()或ShowDialog()方法的时候才会执行。
(3)窗体加载方法的执行时机是在窗体即将显示的时候,在窗体加载方法中不应该有一些任务很重的初始化工
作,因为那样会导致在窗体刚显示时会出现闪烁的情况。一些较小的程序可能体现不出来,当加载的东西
比较多,特别是插件架构的程序时,闪烁的情况就特别严重。所以,比较繁重的初始化工作尽量放到构造方
法中去,等所有初始化工作都完成时再调用窗体的Show()方法就不会出现闪烁的情况了。程序的欢迎界面就
是这样处理的。
(4)当你在设计一个控件的时候,一定要注意到在构造方法中进行初始化和在控件加载方法中初始化的差别。
如,方式一:在构造方法中进行属性的初始化
public class MyControl : UserControl
{
private string _MyText;
public string MyText
{
get { return _MyText; }
set { _MyText = value; }
}
public MyControl()
{
InitializeComponent();
_MyText = "Hello World!";
}
}
这种方式是一种比较正确的方式,我们再来看方式二:在加载方法中进行属性的初始化
public class MyControl : UserControl
{
private string _MyText;
public string MyText
{
get { return _MyText; }
set { _MyText = value; }
}
public MyControl()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
_MyText = "Hello World!";
}
}
有人可能会说,这两种方式不都一样吗,都是将MyText属性设置为"Hello World!"。这样看是看不出什么区别,可是当别人使用你的控件时问题就出现了。在第二种方式中,程序员在窗体设计器中修改了控件的MyText属性设置为了"Changed",可是窗体一显示,该控件的MyText属性仍然显示为"Hello World!"。回去查看自己的代码,发现自动生成的代码也即InitializeComponent()方法中myControl1.MyText = "Changed"也确实修改了,并且在那之后都没有修改过MyText属性,可是为什么其属性还是"Hello World!"呢?
答案相信大家都知道了,就在设计控件时在加载方法中的赋值操作。因为加载方法是在即将显示控件的时候才调用的,所以之前的所有修改都被在加载方法中进行的修改覆盖了。使用该控件的程序员仅仅查看自己代码是根本查不出问题的,所以在设计控件时一定要限制使用这种初始化赋值方式。当然,如你希望使控件的属性仅在运行时才能被修改,忽略在设计时的修改,这种方式还是很适合的。
注:本文转载自 yu000hong 的新浪博客