代码之家  ›  专栏  ›  技术社区  ›  Paul Michaels

在构造函数期间关闭窗体

  •  43
  • Paul Michaels  · 技术社区  · 14 年前

    是否可以在构造函数执行时关闭窗体(或只是在此阶段停止它的显示)?

    我有以下代码:

    public partial class MyForm : Form
    {        
        public MyForm()
        {
            if (MyFunc())
            {
                this.Close();
            }
        }
    }
    

    它在main()中抛出一个objectDisposedException,这里:

        static void Main()
        {            
            ...
    
            // Following line errors
            Application.Run(new MyForm());
        }
    

    我试过像这样检查MyForm的结果:

    static void Main()
    {            
        ...
    
        MyForm frm = new MyForm();
        if (frm != null)
        {
            // Following line errors
            Application.Run(frm);
        }
    }
    

    但这似乎没有帮助。有人能告诉我怎么解决这个问题吗?也许是一种检查表单以查看它是否仍然存在的方法?

    9 回复  |  直到 6 年前
        1
  •  81
  •   Christian    8 年前

    打电话 Close 从窗体的构造函数不可能,因为它将调用 Dispose 在尚未创建的窗体上。若要在构造后关闭表单,请将匿名事件处理程序分配给 Load event 在首次显示表单之前关闭表单:

    public partial class MyForm : Form
    {
        public MyForm()
        {
            if (ShouldClose())
            {
                Load += (s, e) => Close();
                return;
            }
    
            // ...
        }
    
        // ...
    }
    
        2
  •  20
  •   ErikHeemskerk    14 年前

    唯一能做的就是在构造函数中设置一个标志来关闭它,然后在 Shown 事件。当然,如果您这样做,那么移动代码以确定是否应该首先在那里关闭它是有意义的。

        3
  •  17
  •   Dave M NPE    12 年前

    以下各项工作良好:

    public partial class MyForm : Form
    {        
        public MyForm()
        {
            if (MyFunc())
            {
                this.Shown += new EventHandler(MyForm_CloseOnStart);
            }
        }
    
        private void MyForm_CloseOnStart(object sender, EventArgs e)
        {
            this.Close();
        }
    }
    
        4
  •  8
  •   Matthew Abbott    14 年前

    在窗体上调用close()时,它在内部处理窗体并释放任何托管资源。当你这样做的时候:

    Application.Run(new MyForm());
    

    您可能会得到一个ObjectDisposedException。您需要做的是通过属性设置窗体的可见性:

    Application.Run(new MyForm() { Visible = false });
    

    只需确保移除构造函数中对close()的调用,或者甚至将属性赋值也移到那里。

        5
  •  3
  •   Mauro    14 年前

    你能让MyFunc静止吗?然后做如下的事情:

    static void Main() 
    {             
        ... 
        if (MyForm.MyFunc())
        {
            Application.Run(new MyForm()); 
        }
    } 
    

    这本质上会给您相同的控制权来决定窗体是否要被构造?

        6
  •  3
  •   Headers13    12 年前

    我发现向“加载”事件添加处理程序更好,因为这样对话框就永远不会显示。对于“显示的”事件,您可能会短暂地看到对话框打开然后关闭,这可能会令人困惑:

    public partial class MyForm : Form
    {        
        public MyForm()
        {
            if (MyFunc())
            {
                this.Load += MyForm_CloseOnStart;
            }
        }
    
        private void MyForm_CloseOnStart(object sender, EventArgs e)
        {
            this.Close();
        }
    }
    
        7
  •  2
  •   Pollitzer    6 年前

    Environment.Exit(...) 正在为我工作(没有窗口闪烁):

    public partial class MyForm : Form
    {        
        public MyForm()
        {
            if (weShouldClose)
            {
                Environment.Exit(0);
            }
        }
    }
    
        8
  •  2
  •   Harald Coppoolse    6 年前

    我认为关闭构造函数中的窗体是不明智的。如果这样做,表单的用户将不知道是否显示对话框。

    以下代码将是非常正常的使用:

    // in the parent form:
    public void ShowMyForm()
    {
        MyForm form = new MyForm();
        form.propertyA = ...;
        from.propertyB = ...;
        DialogResult dlgResult = form.ShowDialog(this);
        ProcessDialogResult(dlgResult);
    }
    

    如果在构造函数中决定是否应显示表单,则必须在构造后添加代码,以决定是否调用ShowDialog以及是否处理对话框结果。

    此外,是否确定更改属性不会影响窗体是否显示?在未来的变化之后?

    在施工过程中,表单尚未显示/打开。所以我害怕 Close() 做不到你期望的。

    整洁的方法是以“加载”的形式在构造函数中执行您想要执行的检查。为表单加载添加一个事件处理程序,并在事件处理程序中进行检查。使用属性DialogResult指示您决定不显示表单。

    private void FormMain_Load (object sender, EventArgs e)
    {
        if (FormShouldNotLoad())
        {
            this.DialogResult = System.Windows.Forms.DialogResult.Abort;
            Close();
            // Warning, this does not work, see below, (but we're almost there!)
        }
    }
    

    代码的用户可以检查对话框的结果:

    // in the parent form:
    public void ShowMyForm()
    {
        MyForm form = new MyForm();
        form.propertyA = ...;
        from.propertyB = ...;
        DialogResult dlgResult = form.ShowDialog(this);
        switch (dlgResult)
        {
            case System.Windows.Forms.DialogResult.Abort:
                ProcessFormNotLoaded();
                break;
            case System.Windows.Forms.DialogResult.OK:
                ProcessFormOk();
                break;
            // etc.
        }
    }
    

    但是,在窗体加载的事件处理程序中调用close()将不起作用,因为 关闭() 只能在加载完成后正确调用。

    因此,而不是呼叫 关闭() 你应该 BeginInvoke close()函数,因此 Close 加载完成后将调用函数:

    private void FormMain_Load (object sender, EventArgs e)
    {
        if (FormShouldNotLoad())
        {
            this.DialogResult = System.Windows.Forms.DialogResult.Abort;
            // invoke the Close function after Load completed
            this.BeginInvoke(new MethodInvoker( () => this.CancelLoading())
        }
    }
    
        9
  •  0
  •   Bitterblue    10 年前

    如果你想让你的窗户 从未见过
    (没有瞬间打开然后消失的闪烁窗口) :

    public new void Show()
    {
        if (MyFunc())
            base.Show();
        else
            ; // dispose or whatever
    }
    

    虽然 Show(...) 有2个重载和 ShowDialog(...) 也有2个。
    不适用于通过打开的主窗体 Application.Run() . 但无论如何,谁会这么做呢?除了还有一种不使用 应用程序.run() .