C# 加载表单而不显示它
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/66921/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Load a form without showing it
提问by Don Kirkby
Short version: I want to trigger the Form_Load() event without making the form visible. This doesn't work because Show() ignores the current value of the Visible property:
简短版本:我想在不使表单可见的情况下触发 Form_Load() 事件。这不起作用,因为 Show() 忽略了 Visible 属性的当前值:
tasksForm.Visible = false;
tasksForm.Show();
Long version: I have a WinForms application with two forms: main and tasks. The main form is always displayed. The user can either click a button to open the tasks form, or click some buttons that just run a task directly without opening the tasks form.
长版:我有一个包含两种形式的 WinForms 应用程序:主要和任务。始终显示主窗体。用户既可以单击按钮打开任务表单,也可以单击某些按钮直接运行任务,而无需打开任务表单。
When a user asks to run a task directly, I'd like to just call some public methods on the tasks form without showing it. Unfortunately, the task logic depends on stuff that happens in the Form_Load() event. The only way I can find to trigger Form_Load() is to call Show(). The best I've been able to do is to show the form in the minimized state:
当用户要求直接运行任务时,我只想在任务表单上调用一些公共方法而不显示它。不幸的是,任务逻辑取决于在 Form_Load() 事件中发生的事情。我能找到触发 Form_Load() 的唯一方法是调用 Show()。我能做的最好的事情就是以最小化状态显示表单:
tasksForm.WindowState = FormWindowState.Minimized;
tasksForm.Show();
I suppose the cleanest solution would be to pull the tasks logic out of the tasks form and into a controller class. Then I can use that class from the main form and from the tasks form, and only load the tasks form when I need it visible for the user. However, if it's an easy thing to load the form without displaying it, that would be a smaller change.
我想最干净的解决方案是将任务逻辑从任务表单中提取到控制器类中。然后我可以从主窗体和任务窗体中使用该类,并且仅在需要它对用户可见时才加载任务窗体。但是,如果加载表单而不显示它很容易,那将是一个较小的变化。
采纳答案by Shaun Austin
I totally agree with Rich B, you need to look at where you are placing your application logic rather than trying to cludge the WinForms mechanisms. All of those operations and data that your Tasks form is exposing should really be in a separate class say some kind of Application Controller or something held by your main form and then used by your tasks form to read and display data when needed but doesn't need a form to be instantiated to exist.
我完全同意 Rich B,您需要查看您放置应用程序逻辑的位置,而不是试图混淆 WinForms 机制。您的任务表单公开的所有这些操作和数据都应该在一个单独的类中,比如某种应用程序控制器或由您的主表单保存的东西,然后由您的任务表单在需要时读取和显示数据,但不需要需要一个要实例化的表单才能存在。
It probably seems a pain to rework it, but you'll be improving the structure of the app and making it more maintainable etc.
重新设计它可能看起来很痛苦,但是您将改进应用程序的结构并使其更易于维护等。
回答by GEOCHET
It sounds to me like you need to sit down and re-think your approach here. I cannot imagine a single reason your public methods need to be in a form if you are not going to show it. Just make a new class.
在我看来,您需要坐下来重新考虑您的方法。如果您不打算展示它,我无法想象您的公共方法需要采用某种形式的单一原因。只需创建一个新类。
回答by Sam
If you make the method public, then you could access it directly.... however, there could be some unexpected side effects when you call it. But making it public and calling it directly will not draw the screen or open the form.
如果你把方法公开,那么你可以直接访问它......但是,当你调用它时可能会有一些意想不到的副作用。但是公开并直接调用它不会绘制屏幕或打开表单。
回答by McKenzieG1
Move mandatory initialization code for the form class out of the Load
event handler into the constructor. For a Form class, instantiation of an instance (via the constructor), form loading and form visibility are three different things, and don't need to happen at the same time (although they do obviously need to happen in that order).
将表单类的强制初始化代码从Load
事件处理程序中移到构造函数中。对于 Form 类,实例的实例化(通过构造函数)、表单加载和表单可见性是三件不同的事情,不需要同时发生(尽管它们显然需要按顺序发生)。
回答by configurator
From MSDN:
来自 MSDN:
Form.Load
Occurs before a form is displayed for the first time.
Form.Load
在第一次显示表单之前发生。
Meaning the only thing that would cause the form to load, is when it is displayed.Form.Show();
and Form.Visible = true;
are the exact same thing. Basically, behind the scenes, Show checks for various conditions, then sets Visible to true. So obviously, setting visible to false (which it already is) before showing the form is meaningless.
这意味着唯一会导致表单加载的事情是显示时。Form.Show();
并且Form.Visible = true;
是完全一样的东西。基本上,在幕后,Show 检查各种条件,然后将 Visible 设置为 true。很明显,在显示表单之前将可见设置为 false(它已经是)是没有意义的。
But let's forget the technicalities. I completely agree with Rich B and Shaun Austin - the logic shouldn't be in that form anyway.
但是让我们忘记技术细节。我完全同意 Rich B 和 Shaun Austin - 无论如何,逻辑不应该是那种形式。
回答by Jeff Roe
Perhaps it should be noted here that you cancause the form's window to be created without showing the form. I think there could be legitimate situations for wanting to do this.
也许这里应该注意,您可以在不显示表单的情况下创建表单的窗口。我认为可能存在想要这样做的合法情况。
Anyway, good design or not, you can do that like this:
不管怎样,无论设计是否好,你都可以这样做:
MyForm f = new MyForm();
IntPtr dummy = f.Handle; // forces the form Control to be created
I don't think this will cause Form_Load() to be called, but you will be able to call f.Invoke() at this point (which is what I was trying to do when I stumbled upon this SO question).
我认为这不会导致 Form_Load() 被调用,但此时您将能够调用 f.Invoke() (这是我偶然发现这个 SO 问题时试图做的)。
回答by Ben Glancy
Sometimes this would be useful without it being bad design. Sometimes it could be the start of a migration from native to managed.
有时这会很有用,但不是糟糕的设计。有时它可能是从本地迁移到托管的开始。
If you were migrating a c++ app to .NET for example, you may simply make yourwhole app a child window of the .NET form or panel, and gradually migrate over to the .NET by getting rid of your c++ app menu, status bar, toolbar and mapping teh .NEt ones to your app using platform invoke etc...
例如,如果你将一个 c++ 应用程序迁移到 .NET,你可以简单地将你的整个应用程序作为 .NET 窗体或面板的子窗口,然后通过去掉你的 c++ 应用程序菜单、状态栏、工具栏并使用平台调用等将 .NEt 映射到您的应用程序...
Your C++ app may take a while to load, but the .NET form doesn't..in which you may like to hide the .NEt form until your c++ app has initialised itself.
您的 C++ 应用程序可能需要一段时间才能加载,但 .NET 表单不会……在其中您可能希望隐藏 .NEt 表单,直到您的 C++ 应用程序已初始化。
I'd set opacity=0 and visible=false to false after calling show, then when your c++ app loads, then reverse.
我会在调用 show 后将 opacity=0 和 visible=false 设置为 false,然后当您的 C++ 应用程序加载时,然后反转。
回答by Sodoshi
None of the answers solved the original question, so, add the below, call .Show() to load the form without showing it, then call .ShowForm() to allow it to be visible if you want to after:
没有一个答案解决了原始问题,因此,添加以下内容,调用 .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();
}
}