C#在构造函数中closures表单

是否有可能在构造函数正在执行时closures窗体(或仅仅是在此阶段停止显示)?

我有以下代码:

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

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

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

从窗体的构造函数调用Close是不可能的,因为它将调用Dispose在尚未创build的窗体上。 要在closures窗体后build立,分配一个匿名事件处理程序的Load事件closures您的窗体之前,它是第一次显示:

 public partial class MyForm : Form { public MyForm() { if (ShouldClose()) { Load += (s, e) => Close(); return; } // ... } // ... } 

以下运作良好:

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

当您在窗体上调用Close()时,内部将处理表单并释放所有托pipe资源。 当你这样做:

 Application.Run(new MyForm()); 

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

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

只要确保在构造函数中删除了对Close()的调用,甚至可以在那里移动属性赋值。

你可以让MyFunc静态? 然后做一些事情:

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

这基本上会给你同样的控制,是否表格将被构build或不是?

我发现添加一个处理程序到“Load”事件是更好的,因为这种方式从来没有显示对话框。 在“显示”事件中,您可能会短暂地看到对话框打开,然后closures,这可能会令人困惑:

 public partial class MyForm : Form { public MyForm() { if (MyFunc()) { this.Load += MyForm_CloseOnStart; } } private void MyForm_CloseOnStart(object sender, EventArgs e) { this.Close(); } } 

您的表单不会从构造函数中打开。 你想达到什么目的?

如果closures这个表单,那么代码path将完全退出,没有明显的好处(即Application.Run将退出)。 其他人发表了关于使表单隐藏的代码,似乎更有可能。

如果你想让你的窗户永远不被看到
(没有闪烁的窗口瞬间打开,然后消失)

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

虽然Show(...)有2个重载, ShowDialog(...)也有2个。
不适用于通过Application.Run()打开的主窗体。 但是谁呢? 除了还有一种不使用Application.Run()的方式来打开主窗体。

我认为在构造函数中closures表单是不明智的。 如果你这样做,表单的用户不知道是否ShowDialog。

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

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

你将不得不添加特殊的代码来决定是否ShowDialog和是否处理对话框的结果。

此外,您是否确定这些属性不会影响表单是否被显示? 还有未来的变化?

施工期间,表格尚未显示/打开。 所以恐怕Close()没有达到你所期望的。

整洁的方法是在Form_Load中进行检查。 添加表单加载事件处理程序,并在那个时候进行检查。 使用属性DialogResult来表明你决定不显示表单。

 private void FormMain_Load (object sender, EventArgs e) { if (FormShouldNotLoad()) { this.DialogResult = System.Windows.Forms.DialogResult.Cancel; Close(); } } 

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

 // 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.Cancel: ... break; case System.Windows.Forms.DialogResult.OK: ... break; // etc. } } 

然而,这将无法正常工作,因为closures只能在加载完成后才能正确调用。 因此,不应该调用Close(),而应该BeginInvoke Close()函数,因此在加载完成后将调用Close函数:

加载完成后调用Close()的代码如下:

 private void FormMain_Load (object sender, EventArgs e) { if (MyFunc()) { CancelLoading(); } } private delegate void InvokeDelegate(); private void CancelLoading() { // will cancel loading this form this.DialogResult = System.Windows.Forms.DialogResult.Cancel; this.BeginInvoke(new InvokeDelegate(CloseThisForm)); } private void CloseThisForm() { this.Close(); } 

好的一点是,在OnFormClosing和OnFormClosed期间,您完全知道表单的状态:它是完全加载的,所以您在closures时知道该怎么做。