在子构造函数的 InitializeComponent 完成后运行方法,而不在子类中隐式调用

发布于 2024-11-28 22:07:50 字数 676 浏览 2 评论 0原文

我不确定这是否可能,但我希望能够做的是让父基类的所有子级运行基类中定义的方法,而不在子类中显式调用它。

换句话说,我想要实现的是这样的:

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
    }
}

是否有一种模式可以实现这种行为,或者面向方面的编程可能是实现这一目标的一种方法?

I'm not sure if this is possible or not, but what I would like to be able to do is to have all Children of a Parent base class to run a method defined in the base class without explicitly invoking it in the child class.

In other words, what I'd like to achieve is something like this:

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
    }
}

Is there a pattern that could enable this behaviour, or could perhaps Aspect Oriented Programming be a way to achieve this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

谁的年少不轻狂 2024-12-05 22:07:50

您可以改为覆盖 Form.OnLoad 父表单的方法;它保证在表单显示之前被调用。

protected override void OnLoad(EventArgs e)
{
    Setup();

    base.OnLoad(e);
}

You could instead override the Form.OnLoad method of the parent form; it's guaranteed to be called just before the Form is shown.

protected override void OnLoad(EventArgs e)
{
    Setup();

    base.OnLoad(e);
}
灯角 2024-12-05 22:07:50

我认为您只想覆盖 OnLoad方法:

public class Parent
{
    public Parent()
    {
       InitializeComponent();
    }

    protected override void OnLoad(EventArgs e)
    {
        // put initialization code here

        base.OnLoad(e);
    }
}

父子组件初始化时调用。
不要忘记调用 base.OnLoad 以便 Load 事件处理程序(如果有)接收该事件。

I think you just want to override OnLoad method:

public class Parent
{
    public Parent()
    {
       InitializeComponent();
    }

    protected override void OnLoad(EventArgs e)
    {
        // put initialization code here

        base.OnLoad(e);
    }
}

It is called when both parent and child components are initialized.
Don't forget to call base.OnLoad so that Load event handlers, if any, receive the event.

摇划花蜜的午后 2024-12-05 22:07:50

Child 的构造函数将自动调用 Parent 的构造函数(实际上,在调用其自己的代码之前),因此在上面的情况下,Setup 将始终在 Child 类中调用(并且 InitializeComponent 将被调用两次)。

The constructor of Child will automatically call the constructor of Parent (before its own code gets called, in fact), so in your situation above, Setup will always be called in the Child class (and InitializeComponent will be called twice).

爱本泡沫多脆弱 2024-12-05 22:07:50

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 之后再次设置了大小,最后一行只是使表单在屏幕上居中。

Running code in the Load event or OnLoad is often the worst solution.

If you want to run code once after the form load you can use Shown event, otherwise the form looks laggy and unresponsive you you have long running code (controls are shown one after another).

If you really want to run code after the child constructor but before the load event, overriding OnHandleCreated is your best choice.

However: There is (at least) one thing left that won't work. I had a form base class that set a specific startup position / size regardless of what the child form defined. Every effort I made failed or the form was visible on the wrong location for a split second. This is how I solved it:

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);
    }
}

Here is the tricky part: After yo set the size, it somehow gets reverted on some point in the load process. The same thing happens if you call Screen.FromControl(form). I suppose because Screen.FromControl eventually calls Screen.FromHandle and that will cause the handle to be created. But I suppose it does something else, too because if I run the above code in the OnHandleCreated method (after calling base.OnHandleCreated of course) it won't get the desired result. Because of this I set the size again after Screen.FromControl the last line is just to center the form on the screen.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文