当我处理 UserControl 时,关闭由 UserControl 的按钮打开的模态窗体

Close the modal form which is opened by a button of a UserControl when I dispose the UserControl

我有一个应用程序,我需要确保使用 ShowDialog() 单击用户控件上的按钮打开的表单将在我处理用户控件时关闭并处理。

我正在通过计时器在主窗体中调用 userControl.Dispose()

有什么办法可以做到吗?

谢谢...

以下是有关表格流程的更多详细信息:

我的应用程序的 MainForm 正在创建一个 UserControl,它有一个 Button。比当用户单击用户控件的按钮时,它会显示一个使用 ShowDialog.

的模型表单

与此同时,几分钟后,主窗体中的计时器将现有用户控件替换为用户控件的另一个实例。主窗体调用上一个用户控件的Dispose方法,然后显示新的。

但问题是模态对话框仍在屏幕上打开,挡住了主窗体。我想关闭它,放在ShowDialog方法后面的代码应该不会执行。

能否修改自动关闭的表单?如果是这样,请尝试将以下内容添加到每个表单中:

protected override void OnShown(EventArgs e)
{
    base.OnShown(e);

    if (this.Owner != null)
        this.Owner.HandleDestroyed += onOwnerHandleDestroyed;
}

void onOwnerHandleDestroyed(object sender, EventArgs e)
{
    this.Close();
}

注意:您已经在使用 Dispose() 关闭主窗体,所以这应该可以。但是,如果您使用 Close() 关闭主窗体,那么它将不起作用,因为 Close() 不会关闭窗体,如果它是任何模式对话框的父窗体。

简答

您可以订阅 UserControlDisposed 事件并关闭它显示的表单。关于问题下的评论,看起来你有一个包含 ButtonUserControl 并且在按钮的 Click 事件中,你使用 [=18 显示 Form =].

要关闭和处理表单,您需要在 UserControl 将表单显示为对话框之前订阅 Disposed 事件。

更多详情

如果你想根据表单的对话结果决定运行一些逻辑,你可以检查对话结果,如果没问题,运行你需要的自定义逻辑。

为了稍微增强流程,您可以在用户控件中定义一些事件和属性,并在主窗体中处理它们:

  • OKSelected事件,如果对话结果正常,可以在关闭对话后立即触发。它会让您在主窗体中处理此事件,例如,如果用户在对话框中单击“确定”,则停止计时器。
  • ProcessingFinished,在对话框结果OK的情况下关闭对话框完成一些处理后可以提出。您可以在主窗体中处理此问题,例如再次启动计时器。
  • 您可以定义一些属性,以防您想与主窗体交流一些值。

以下是主要形式的代码示例:

MyUserControl uc = null;
private void timer1_Tick(object sender, EventArgs e)
{
    if (!(uc == null || uc.IsDisposed || uc.Disposing))
    {
        this.Controls.Remove(uc);
        uc.Dispose();
    }
    uc = new MyUserControl();
    this.Controls.Add(uc);
    uc.OKSelected += (obj, args) => { timer1.Stop(); };
    uc.ProcessingFinished += (obj, args) =>
    {
        MessageBox.Show(uc.Info);
        timer1.Start();
    };
}

下面是用户控件的示例:

public partial class MyUserControl : UserControl
{
    public MyUserControl() { InitializeComponent(); }
    public EventHandler OKSelected;
    public EventHandler ProcessingFinished;
    public string Info { get; private set; }
    private void button1_Click(object sender, EventArgs e)
    {
        using (var f = new Form()) {
            var button = new Button() { Text = "OK" };
            f.Controls.Add(button);
            button.DialogResult = DialogResult.OK;
            this.Disposed += (obj, args) => {
                if (!(f.IsDisposed || f.Disposing)) {
                    f.Close(); f.Dispose();
                }
            };
            if (f.ShowDialog() == DialogResult.OK) {
                //If you need, raise the OKSelected event
                //So you can handle it in the main form, for example to stop timer
                OKSelected?.Invoke(this, EventArgs.Empty);
                //
                //Do whatever you need to do after user closed the dialog by OK
                //
                //If you need, raise the ProcessingFinished event
                //So you can handle it in the main form, for example to start timer
                //You can also set some properties to share information with main form
                Info = "something";
                ProcessingFinished?.Invoke(this, EventArgs.Empty);
            }
        }
    }
}