让方法在子构造器的InitializeComponent完成后运行,而无需在子类中隐式调用
本文关键字:子类 调用 构造器 方法 InitializeComponent 运行 | 更新日期: 2023-09-27 18:04:53
我不确定这是否可能,但我希望能够做的是让Parent基类的所有子类运行在基类中定义的方法,而无需在子类中显式调用它。
换句话说,我想实现的是这样的:
public class Parent
{
public Parent()
{
InitializeComponent();
Setup(); // not run here if this instance is a child of parent
}
protected void Setup()
{
// code that depends on InitializeComponent being called in
// both the parent and any Child's classes
}
}
public class Child : Parent
{
public Child()
{
InitializeComponent();
//Setup(); is invoked here, without having to explicitly
// invoke in all children of Parent
}
}
是否有一种模式可以启用这种行为,或者也许面向方面编程是实现这一目标的一种方式?
你可以重写父表单的Form.OnLoad
方法;它保证在表单显示之前被调用。
protected override void OnLoad(EventArgs e)
{
Setup();
base.OnLoad(e);
}
我想你只是想重写OnLoad
方法:
public class Parent
{
public Parent()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
// put initialization code here
base.OnLoad(e);
}
}
在父组件和子组件初始化时调用。
不要忘记调用base.OnLoad
,以便Load
事件处理程序(如果有的话)接收事件。
Child的构造函数将自动调用Parent的构造函数(实际上,在它自己的代码被调用之前),所以在上面的情况下,Setup将始终在Child类中被调用(InitializeComponent将被调用两次)。
在Load
或OnLoad
事件中运行代码通常是最糟糕的解决方案。
如果你想在表单加载后运行代码一次,你可以使用Shown
事件,否则表单看起来滞后和无响应,你有长时间运行的代码(控件一个接一个地显示)
如果你真的想在子构造函数之后但在加载事件之前运行代码,重写OnHandleCreated是你最好的选择。
然而,(至少)有一件事是行不通的。我有一个表单基类,它设置了一个特定的启动位置/大小,而不管子表单定义了什么。我所做的每一次努力都失败了,或者表单在错误的位置有一瞬间是可见的。我是这样解决的:
public class MyForm : Form
{
private Size defaultSize;
public MyForm()
{
InitializeComponent();
this.defaultSize = this.Size;
this.fireOnBeforeLoad = true;
}
public new void ResumeLayout(bool performLayout)
{
base.ResumeLayout(performLayout);
if (fireOnBeforeLoad)
{
fireOnBeforeLoad = false;
OnBeforeLoad();
}
}
protected virtual void OnBeforeLoad()
{
form.WindowState = FormWindowState.Normal;
form.Size = defaultSize;
form.FormBorderStyle = FormBorderStyle.FixedDialog;
var area = Screen.FromControl(form).WorkingArea;
form.Size = defaultSize;
form.Location = new System.Drawing.Point(
(int)(area.Width - form.Width) / 2,
(int)(area.Height - form.Height) / 2);
}
}
这里是棘手的部分:在设置大小之后,它在加载过程中的某个点以某种方式被恢复。如果调用Screen.FromControl(form)
,也会发生同样的事情。我想是因为Screen.FromControl
最终调用Screen.FromHandle
,这将导致句柄被创建。但我认为它也做了其他事情,因为如果我在OnHandleCreated
方法中运行上面的代码(当然是在调用base.OnHandleCreated
之后),它不会得到想要的结果。因此,我在Screen.FromControl
之后再次设置大小,最后一行只是在屏幕上的窗体中心