首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多形式应用程序显示和隐藏表单的最佳实践?

多形式应用程序显示和隐藏表单的最佳实践?
EN

Stack Overflow用户
提问于 2012-02-27 09:22:28
回答 4查看 53K关注 0票数 19

在StackOverflow上有大量的问题,询问如何隐藏Form1和显示Form2。通常情况下,有几个不同的答案:

1)

代码语言:javascript
复制
// Program.cs
Application.Run(new Form1());
// Form1.cs
Form2 form2 = new Form2();
form2.Show();
this.Hide();

2)

代码语言:javascript
复制
// 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>()的东西。

但我想知道有更多经验的人用的是什么。同样,这些解决方案不应该是快速攻击。它们应该是design-oriented,,或许是architectural,和的长期解决方案

编辑:

对于任何可能遇到同样问题的人来说,这都是一个相当普遍的问题(所以需求是非常开放的)。不过,我不需要在启动时显示多个表单。而且,我没有MDI表单。我可能有一些模态形式,但它们大多是非模态的.

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-02-27 10:17:38

我在这里以一般的方式回答。

我认为单例模式不适合表单管理。通常,您希望向窗体传递某些上下文参数,并且可能希望打开同一窗体的多个实例。所以单身人士不太适合我。

我认为表单管理应该很简单。

例如,如果您想从另一个表单中显示一个模态表单,我会编写一些非常简单的内容:

代码语言:javascript
复制
private void button1_Click(object sender, EventArgs e)
{
    using (ModalForm1 frm = new ModalForm1(myParam))
    {
        frm.ShowDialog();

        if (frm.MyResultProperty == ...)
        {
            // Do some job here
        }
    }
}

当然,您可以编写一些接口/泛型语法,以避免一些代码重复,以防您想要显示很多模态形式:

代码语言:javascript
复制
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;
    }
}

但说实话,我觉得有点过火了。

第二点:如果表单没有完全遵循这个特定的行为(ShowDialog()然后设置了一个Result属性),那么您必须编写另一个Interface...etc。

如果这种类型的语法(泛型,interfaces...etc)。它不会减少编写的代码行数或复杂度或可维护性(很显然,我们不能说这是真的),那么它就非常无用了。

编辑:

表单管理实际上取决于您的用例。

  • 如果您有20个可以同时显示的表单,那么您应该想到一个FormManager概念(或者更好一些:考虑如何通过减少可能打开的表单的数量来提高用户体验),如果您有一些相对简单的东西(2-3种非模态表单同时+ 3-4种可能的模式表单),那么我不会编写复杂的代码来管理这些表单。

通常,用于启动应用程序的表单(即关闭时停止程序的表单,即作为Application.Run()参数的表单)负责其他表单。您有一个主窗体和多个子窗体。如果您的情况确实不同,那么可能有一些更聪明的东西可以编写,但它将取决于您的情况。我不认为一个人能为表单管理的一般问题提供一个通用的好答案。

老实说,如果您想要一些真正可维护的东西,请尽量减少(尽可能多地)可以同时显示的表单数量。在大多数情况下,多个显示的非模式表单不能提供良好的用户体验,如果表单相互依赖,表单生命周期管理可能会出现问题。

票数 6
EN

Stack Overflow用户

发布于 2012-11-15 22:12:58

除了最简单的场景--在应用程序的生命周期中运行的单个主窗体(具有短暂的子窗体) --建议创建一个继承自ApplicationContext的类。也没那么复杂:

代码语言:javascript
复制
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();
    }
}

Application.RunProgram.cs中可以使用FormManager的静态实例。

代码语言:javascript
复制
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事件:

代码语言:javascript
复制
var f3 = FormManager.Current.CreateForm<Form3>();
f3.Show();
var f4 = FormManager.Current.CreateForm<Form4>();
f4.ShowDialog();

如果您更喜欢new Form3();而不是对FormManager.CreateForm的调用,则可以在FormManager上创建RegisterForm方法

代码语言:javascript
复制
public void RegisterForm(Form frm) {
    frm.FormClosed += onFormClosed;
}

并在每个新的RegisterForm上调用Form

代码语言:javascript
复制
var f3 = new Form3();
FormManager.Current.RegisterForm(f3);
var f4 = new Form4();
FormManager.Current.RegisterForm(f4);

(注:如果您的所有表单都继承自某个基类,那么可以在基类构造函数中调用它,而不是手动调用每个新实例的RegisterForm。)

注意,Application.OpenForms只返回当前可见的那些表单。如果应用程序不应该退出,只要仍然有隐藏表单打开,那么FormManager将不得不使用一些集合来跟踪所有表单。该集合将决定是否退出应用程序。

代码语言:javascript
复制
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;
}
票数 14
EN

Stack Overflow用户

发布于 2012-02-27 09:54:36

根据应用程序的大小,您可以查看Microsoft库,特别是CAB块。

这应该会给你一个好的开始。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9462592

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档