C# 多表单应用程序显示和隐藏表单的最佳实践?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9462592/
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
Best practices for multi-form applications to show and hide forms?
提问by Jason
There are tons of questions on StackOverflow asking how to hide Form1 and show Form2. And, usually, a few different answers crop up:
StackOverflow 上有很多关于如何隐藏 Form1 和显示 Form2 的问题。而且,通常会出现一些不同的答案:
1)
1)
// Program.cs
Application.Run(new Form1());
// Form1.cs
Form2 form2 = new Form2();
form2.Show();
this.Hide();
2)
2)
// Program.cs
Form1 form1 = new Form1();
Form2 form2 = new Form2();
form1.Show();
form2.Show();
Application.Run();
...etc..
...etc..
I'm not looking for a simple disposable solution like #1. I'm looking for best form management practices. An application with 5-8 forms, opening and closing one another frequently - what's the best way to manage these forms?
我不是在寻找像#1 这样简单的一次性解决方案。我正在寻找最佳表单管理实践。一个有 5-8 个表单的应用程序,频繁地打开和关闭彼此 - 管理这些表单的最佳方法是什么?
My idea was to make each form a (lazy?) Singleton and bury them in a FormsManagerclass of some sort (like solution #2 but ++). And then individual forms might call something like FormsManager.GetForm<WelcomeDialog>().
我的想法是让每个表单都成为(懒惰的?)单例并将它们埋在某种FormsManager类中(如解决方案 #2 但 ++)。然后单个表单可能会调用类似FormsManager.GetForm<WelcomeDialog>().
But I was wondering what people with more experience used. Again, these solutions shouldn't be quick hacks. They should be design-oriented, maybe architectural, and long-term solutions.
但我想知道有更多经验的人使用了什么。同样,这些解决方案不应该是快速的黑客。它们应该是面向设计的,也许是架构的,以及长期的解决方案。
Edits:
编辑:
This is a pretty generic question (so the requirements are pretty open) for anybody who might have the same trouble. Specific to my situation though, I don't need multiple forms shown at startup. Also, I have no MDI forms. I may have a few modal forms, but they are mostly non-modal.
对于任何可能遇到同样问题的人来说,这是一个非常通用的问题(因此要求非常开放)。不过,具体到我的情况,我不需要在启动时显示多个表单。另外,我没有 MDI 表格。我可能有一些模态形式,但它们大多是非模态的。
采纳答案by ken2k
I'm answering in a general manner here.
我在这里以一般的方式回答。
I don't think a singleton pattern would fit well with form management. Generally, you want to pass some context parameter to the form, and you might want to open multiple instances of the same form. So a singleton doesn't fit well IMO.
我认为单例模式不太适合表单管理。通常,您希望向表单传递一些上下文参数,并且您可能希望打开同一表单的多个实例。所以单身人士不太适合IMO。
I think form management should be simple.
我认为表单管理应该很简单。
For instance, if you want to display a modal form from another form, I would write something really straightforward:
例如,如果你想从另一个表单显示一个模态表单,我会写一些非常简单的东西:
private void button1_Click(object sender, EventArgs e)
{
using (ModalForm1 frm = new ModalForm1(myParam))
{
frm.ShowDialog();
if (frm.MyResultProperty == ...)
{
// Do some job here
}
}
}
Of course you could write some interface/generics syntax to avoid a little code duplication in case you want to display a lot of modal forms:
当然,您可以编写一些接口/泛型语法来避免一些代码重复,以防您想显示大量模态表单:
public interface IFormResult<T>
{
T Result { get; set; }
}
public class ModalForm1 : Form, IFormResult<string>
{
public ModalForm1()
{
InitializeComponent();
this.Result = "My result";
}
public string Result { get; set; }
}
private void button1_Click(object sender, EventArgs e)
{
string res = ShowModalForm<ModalForm1, string>();
}
private static T2 ShowModalForm<T1, T2>()
where T1 : Form, IFormResult<T2>, new()
{
using (T1 form = new T1())
{
form.ShowDialog();
return form.Result;
}
}
But honestly, I feel like it's a bit overingeneered.
但老实说,我觉得这有点过分了。
Second point: if your form doesn't exactly follows this specific behavior (ShowDialog()then a Resultproperty is set), then you must write another Interface...etc.
第二点:如果你的表单没有完全遵循这个特定的行为(ShowDialog()然后Result设置一个属性),那么你必须编写另一个接口......等。
If this type of syntax (generics, interfaces...etc.) doesn't reduce the number of lines of code written OR the complexity OR the maintainability (and obviously we can't say it's really the case here), then it's pretty useless IMO.
如果这种类型的语法(泛型、接口等)没有减少编写的代码行数或复杂性或可维护性(显然我们不能在这里说真的如此),那么它就很漂亮无用的海事组织。
Edit:
编辑:
Form management really depends on your use case.
表单管理实际上取决于您的用例。
- If you have say 20 forms that can be displayed at the same time, then you should think of a
FormManagerconcept (or better: think about how to improve the user experience by reducing the number for possible opened forms) - If you have something relatively simple (2-3 modeless forms at the same time + 3-4 possible modal forms), I wouldn't write complex code to manage those forms.
- 如果您说可以同时显示 20 个表单,那么您应该考虑一个
FormManager概念(或者更好:考虑如何通过减少可能打开的表单的数量来改善用户体验) - 如果您有一些相对简单的东西(同时有 2-3 个无模式表单 + 3-4 个可能的模态表单),我不会编写复杂的代码来管理这些表单。
Generally, the form that is used to start the application (i.e. the form that stops the program when closed, which is the form that is a parameter of Application.Run()) is responsible of other forms. You have one main form, and multiples child forms. If your case is really different, then there is probably something smarter to write, but it'll depend on your case. I don't think one can provide a general good answer to the general problematic of form management.
一般情况下,用于启动应用程序的窗体(即关闭时停止程序的窗体,它是 的参数窗体Application.Run())负责其他窗体。你有一个主窗体,和多个子窗体。如果你的情况真的不同,那么可能写一些更聪明的东西,但这取决于你的情况。我不认为人们可以为表单管理的一般问题提供一般好的答案。
Honestly, if you want something really maintainable, try to reduce (as much as possible) the number of forms that can be shown at the same time. Multiple displayed modeless forms at the same time doesn't offer a good user experience in most cases, and form lifetime management can be problematic if forms are dependent on each other.
老实说,如果您想要真正可维护的东西,请尝试(尽可能多地)减少可以同时显示的表单数量。在大多数情况下,同时显示多个无模式表单并不能提供良好的用户体验,如果表单相互依赖,表单生命周期管理可能会出现问题。
回答by Amen Ayach
I use this trick. Lets say form1 is the main form:
我用这个技巧。让我们说 form1 是主要形式:
private void button1_Click(object sender, EventArgs e)
{
LoadForm(new Form2());
}
private void LoadForm(Form frm)
{
frm.FormClosed += new FormClosedEventHandler(frm_FormClosed);
this.Hide();
// Here you can set a bunch of properties, apply skins, save logs...
// before you show any form
frm.Show();
}
void frm_FormClosed(object sender, FormClosedEventArgs e)
{
this.Show();
}
Therefore; when you open any form closed (except form1), form1 will reappear again.
所以; 当您打开任何关闭的表单时(除了 form1),form1 将再次出现。
Update
更新
using (Form2 frm = new Form2())
{
if (frm.ShowDialog() = DialogResult.ok)
{
//Do some things...
}
}
In this case there is no need to hide previous form.
在这种情况下,无需隐藏以前的表单。
回答by Steoates
Depending on the size of your application, Id say have a look at the Microsoft Enterprise library and specifically the CAB block.
根据您的应用程序的大小,我可以说看看 Microsoft Enterprise 库,特别是 CAB 块。
That should give you a good start.
这应该给你一个良好的开端。
回答by Zev Spitz
In anything other than the most straightforward scenario -- a single main form running for the lifetime of the application, with short-lived child forms -- it is recommended to create a class that inherits from ApplicationContext. It isn't that complicated:
除了最直接的场景——在应用程序的整个生命周期内运行的单个主窗体,以及短暂的子窗体——之外,建议创建一个继承自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();
}
}
and Application.Runin Program.cscan use the static instance of FormManager:
并且Application.Run在Program.cs可以使用的静态实例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);
}
}
During the lifetime of the application, new forms should be created via CreateForm, in order to register the onFormClosedmethod with the FormClosedevent:
在应用程序的生命周期内,应通过 来创建新表单CreateForm,以便向事件注册该onFormClosed方法FormClosed:
var f3 = FormManager.Current.CreateForm<Form3>();
f3.Show();
var f4 = FormManager.Current.CreateForm<Form4>();
f4.ShowDialog();
If you prefer new Form3();over calls to FormManager.CreateForm, you can create a RegisterFormmethod on FormManager:
如果您更喜欢new Form3();调用FormManager.CreateForm,则可以RegisterForm在 上创建一个方法FormManager:
public void RegisterForm(Form frm) {
frm.FormClosed += onFormClosed;
}
and call RegisterFormon each new Form:
并呼吁RegisterForm每个新的Form:
var f3 = new Form3();
FormManager.Current.RegisterForm(f3);
var f4 = new Form4();
FormManager.Current.RegisterForm(f4);
(NB. If all your forms inherit from some base class, then instead of manually calling RegisterFormfor each new instance, you could call it in the base class constructor.)
(注意。如果您的所有表单都继承自某个基类,那么RegisterForm您可以在基类构造函数中调用它,而不是手动调用每个新实例。)
Note that Application.OpenFormsonly returns those forms that are currently visible. If the application shouldn't exit as long as there are still hidden forms open, then FormManagerwill have to use some collection to keep track of all the forms. That collection will determine whether to quit the application or not.
请注意,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;
}
回答by Jagdish
public partial class Form1 : Form
{
private static Form1 inst;
public static Form1 GetForm
{
get
{
if (inst == null || inst.IsDisposed)
{
inst = new Form1();
}
return inst;
}
}
public Form1()
{
InitializeComponent();
inst = this;
}
private void button1_Click(object sender, EventArgs e)
{
Form2.GetForm.Show();
this.Hide();
}
}
public partial class Form2 : Form
{
private static Form2 inst;
public static Form2 GetForm
{
get
{
if (inst == null || inst.IsDisposed)
inst = new Form2();
return inst;
}
}
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form1.GetForm.Show();
this.Hide();
}
private void Form2_FormClosed(object sender, FormClosedEventArgs e)
{
Form1.GetForm.Show();
}
}
if you have more than two form then create another form as From2
如果您有两个以上的表单,则创建另一个表单作为 From2

