加载表单而不显示它

简短版本:我想触发Form_Load()事件而不使表单可见。 这不起作用,因为Show()忽略Visible属性的当前值:

tasksForm.Visible = false; tasksForm.Show(); 

长版本:我有一个WinForms应用程序有两种forms:main和tasks。 始终显示主窗体。 用户可以单击按钮打开任务表单,也可以单击某些直接运行任务的按钮而无需打开任务表单。

当用户要求直接运行任务时,我想在任务表单上调用一些公共方法而不显示它。 不幸的是,任务逻辑依赖于Form_Load()事件中发生的事情。 我能找到触发Form_Load()的唯一方法是调用Show()。 我能做的最好的事情是在最小化状态下显示表单:

 tasksForm.WindowState = FormWindowState.Minimized; tasksForm.Show(); 

我认为最干净的解决方案是将任务逻辑从任务表单中拉出来并转换为控制器类。 然后我可以从主窗体和任务窗体中使用该类,只在我需要为用户显示时加载任务窗体。 但是,如果加载表单而不显示它是一件容易的事情,那将是一个较小的变化。

我完全同意Rich B,你需要看看你放置应用程序逻辑的位置,而不是试图修改WinForms机制。 您的任务表单公开的所有这些操作和数据应该在一个单独的类中说某种应用程序控制器或您的主表单所持有的东西然后由您的任务表单用于在需要时读取和显示数据但不是需要一个表格来实例化存在。

重做它可能看起来很痛苦,但你会改进应用程序的结构并使其更易于维护等。

也许这里应该注意,您可以在不显示表单的情况下创建表单的窗口。 我认为可能存在想要这样做的合法情况。

无论如何,好的设计与否,你可以这样做:

 MyForm f = new MyForm(); IntPtr dummy = f.Handle; // forces the form Control to be created 

我不认为这会导致调用Form_Load(),但是你可以在这一点上调用f.Invoke()(这是我在偶然发现这个问题时试图做的事情)。

听起来像你需要坐下来重新思考你的方法。 如果你不打算展示它,我无法想象你的公共方法需要在一个表单中的一个原因。 做一个新课。

来自MSDN:

Form.Load
在第一次显示表单之前发生。

这意味着唯一会导致表单加载的是它何时被显示。
Form.Show();Form.Visible = true; 是完全一样的。 基本上,在幕后,Show会检查各种条件,然后将Visible设置为true。 很明显,在显示表单之前将visible设置为false(它已经是)是没有意义的。

但是让我们忘记技术细节。 我完全赞同Rich B和Shaun Austin – 无论如何逻辑不应该是那种forms。

有时,如果没有糟糕的设计,这将是有用的。 有时它可能是从本机迁移到托管的开始。

例如,如果您要将c ++应用程序迁移到.NET,您可以简单地将您的应用程序设置为.NET表单或面板的子窗口,并通过删除您的c ++应用程序菜单,状态栏,逐步迁移到.NET。工具栏和映射teh。使用平台调用等到你的应用程序…

您的C ++应用程序可能需要一段时间才能加载,但.NET表单没有..您可能希望隐藏.NEt表单,直到您的c ++应用程序已初始化为止。

我在调用show之后将opacity = 0和visible = false设置为false,然后当你的c ++应用程序加载时,然后反向。

如果你将方法设为公共,那么你可以直接访问它….但是,当你调用它时可能会有一些意想不到的副作用。 但是将其公开并直接调用它不会绘制屏幕或打开表单。

将表单类的强制初始化代码从Load事件处理程序移动到构造函数中。 对于Form类,实例的实例化(通过构造函数),表单加载和表单可见性是三个不同的事情,并且不需要同时发生(尽管它们显然需要按此顺序发生)。

这些答案都没有解决原始问题,因此,添加下面的内容,调用.Show()加载表单而不显示它,然后调用.ShowForm()以允许它在以下情况下可见:

 private volatile bool _formVisible; protected override void SetVisibleCore(bool value) { base.SetVisibleCore(_formVisible); } public void ShowForm() { _formVisible = true; if (InvokeRequired) { Invoke((Action) Show); } else { Show(); } }