c# - 多表单应用程序显示和隐藏表单的最佳实践?

标签 c# winforms design-patterns architecture

<分区>

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

关于c# - 多表单应用程序显示和隐藏表单的最佳实践?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9462592/

相关文章:

c# - 使用带参数的 JQuery 调用 asmx web 服务导致 500 错误

c# - 如何自定义像这样的按钮控件?

c# - 计算html文件表格中有多少列和行

winforms - 无法使用 DevExpress WinForms XtraTab 更改 TabPage 的背景色

java - 快速询问 : function that prints array of cells - should it be inside my cell class definition?

ios - 模型操作属于应用程序设计模式的什么地方?

c# - 将 linq 与 PropertyInfo 结合使用

c# - AspNet 用户声称丢失

java - 数学表达式解析器的设计问题

c# - List<t> 可以被多个线程访问吗?