StackOverflow 上有大量问题询问如何隐藏 Form1 并显示 Form2。通常,会出现一些不同的答案:
1)
// Program.cs
Application.Run(new Form1());
// Form1.cs
Form2 form2 = new Form2();
form2.Show();
this.Hide();
2)
// Program.cs
Form1 form1 = new Form1();
Form2 form2 = new Form2();
form1.Show();
form2.Show();
Application.Run();
...etc..
我不是在寻找像 #1 这样简单的一次性解决方案。我正在寻找最佳表单管理实践。一个应用程序有 5-8 个表单,经常打开和关闭另一个表单 - 管理这些表单的最佳方式是什么?
我的想法是让每个表单成为(懒惰的?)单例并将它们埋在 FormsManager
中。某种类(如解决方案#2 但++)。然后个别表格可能会调用类似 FormsManager.GetForm<WelcomeDialog>()
的内容.
但我想知道有更多经验的人使用什么。同样,这些解决方案不应该是快速破解。它们应该是面向设计,也许是架构和长期解决方案。
编辑:
对于可能遇到同样问题的任何人来说,这是一个非常普遍的问题(因此要求非常开放)。不过,针对我的具体情况,我不需要在启动时显示多种形式。另外,我没有 MDI 表格。我可能有一些模态形式,但它们大多是非模态的。
除了最直接的场景——在应用程序的整个生命周期内运行一个主窗体,以及短暂的子窗体——建议创建一个继承自 ApplicationContext
的类。 .没那么复杂:
class FormManager : ApplicationContext {
//When each form closes, close the application if no other open forms
private void onFormClosed(object sender, EventArgs e) {
if (Application.OpenForms.Count == 0) {
ExitThread();
}
}
//Any form which might be the last open form in the application should be created with this
public T CreateForm<T>() where T : Form, new() {
var ret = new T();
ret.FormClosed += onFormClosed;
return ret;
}
//I'm using Lazy here, because an exception is thrown if any Forms have been
//created before calling Application.SetCompatibleTextRenderingDefault(false)
//in the Program class
private static Lazy<FormManager> _current = new Lazy<FormManager>();
public static FormManager Current => _current.Value;
//Startup forms should be created and shown in the constructor
public FormManager() {
var f1 = CreateForm<Form1>();
f1.Show();
var f2 = CreateForm<Form2>();
f2.ShowDialog();
}
}
和Program.cs
中的Application.Run
可以使用FormManager
的静态实例:
static class Program {
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(FormManager.Current);
}
}
在应用程序的生命周期中,应通过CreateForm
创建新表单,以便将onFormClosed
方法注册到FormClosed
事件:
var f3 = FormManager.Current.CreateForm<Form3>();
f3.Show();
var f4 = FormManager.Current.CreateForm<Form4>();
f4.ShowDialog();
如果您更喜欢 new Form3();
而不是调用 FormManager.CreateForm
,您可以在 FormManager 上创建一个 RegisterForm
方法
:
public void RegisterForm(Form frm) {
frm.FormClosed += onFormClosed;
}
并在每个新的 Form
上调用 RegisterForm
:
var f3 = new Form3();
FormManager.Current.RegisterForm(f3);
var f4 = new Form4();
FormManager.Current.RegisterForm(f4);
(注意。如果您的所有表单都继承自某个基类,那么您可以在基类构造函数中调用它,而不是为每个新实例手动调用 RegisterForm
。)
请注意,Application.OpenForms
仅返回那些当前可见的表单。如果只要仍有隐藏的表单打开,应用程序就不应退出,则 FormManager
将不得不使用一些集合来跟踪所有表单。该集合将决定是否退出应用程序。
class FormManager : ApplicationContext {
private List<Form> forms = new List<Form>();
private void onFormClosed(object sender, EventArgs e) {
forms.Remove((Form)sender);
if (!forms.Any()) {
ExitThread();
}
}
public void RegisterForm(Form frm) {
frm.FormClosed += onFormClosed;
forms.Add(frm);
}
public T CreateForm<T>() where T : Form, new() {
var ret = new T();
RegisterForm(ret);
return ret;
}
private static Lazy<FormManager> _current = new Lazy<FormManager>();
public static FormManager Current => _current.Value;
}