Jas*_*son 16 c# architecture design-patterns winforms
StackOverflow上有很多问题,询问如何隐藏Form1并显示Form2.而且,通常会出现一些不同的答案:
1)
// Program.cs
Application.Run(new Form1());
// Form1.cs
Form2 form2 = new Form2();
form2.Show();
this.Hide();
Run Code Online (Sandbox Code Playgroud)
2)
// Program.cs
Form1 form1 = new Form1();
Form2 form2 = new Form2();
form1.Show();
form2.Show();
Application.Run();
Run Code Online (Sandbox Code Playgroud)
...etc..
我不是在寻找像#1这样简单的一次性解决方案.我正在寻找最佳的表单管理实践.一个5-8种形式的应用程序,经常打开和关闭 - 管理这些表单的最佳方法是什么?
我的想法是让每个形式成为一个(懒惰的?)Singleton并将它们埋在某种FormsManager类中(比如解决方案#2但是++).然后个别形式可能会称之为FormsManager.GetForm<WelcomeDialog>().
但我想知道有更多经验的人使用过什么.同样,这些解决方案不应该是快速破解.它们应该是面向设计的,可能是架构的,也是长期的解决方案.
编辑:
对于可能遇到同样问题的人来说,这是一个非常通用的问题(因此要求非常开放).具体到我的情况,我不需要在启动时显示多个表单.另外,我没有MDI表格.我可能有一些模态形式,但它们大多是非模态的.
Zev*_*itz 10
除了最直接的场景之外的任何事情 - 在应用程序的生命周期中运行的单个主窗体,使用短期子窗体 - 建议创建一个继承自的类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();
}
}
Run Code Online (Sandbox Code Playgroud)
并且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);
}
}
Run Code Online (Sandbox Code Playgroud)
在应用程序的生命周期中,应该通过以下方式创建新表单:CreateForm为了向事件注册onFormClosed方法FormClosed:
var f3 = FormManager.Current.CreateForm<Form3>();
f3.Show();
var f4 = FormManager.Current.CreateForm<Form4>();
f4.ShowDialog();
Run Code Online (Sandbox Code Playgroud)
如果您更喜欢new Form3();通话FormManager.CreateForm,则可以创建一个RegisterForm方法FormManager:
public void RegisterForm(Form frm) {
frm.FormClosed += onFormClosed;
}
Run Code Online (Sandbox Code Playgroud)
并呼吁RegisterForm每个新的Form:
var f3 = new Form3();
FormManager.Current.RegisterForm(f3);
var f4 = new Form4();
FormManager.Current.RegisterForm(f4);
Run Code Online (Sandbox Code Playgroud)
(注意:如果所有表单都从某个基类继承,那么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;
}
Run Code Online (Sandbox Code Playgroud)
我在这里以一般方式回答.
我认为单例模式不适合表单管理.通常,您希望将一些上下文参数传递给表单,并且您可能希望打开同一表单的多个实例.因此单身人士不适合IMO.
我认为表单管理应该很简单.
例如,如果你想从另一个表单中显示一个模态表单,我会写一些非常简单的东西:
private void button1_Click(object sender, EventArgs e)
{
using (ModalForm1 frm = new ModalForm1(myParam))
{
frm.ShowDialog();
if (frm.MyResultProperty == ...)
{
// Do some job here
}
}
}
Run Code Online (Sandbox Code Playgroud)
当然,你可以编写一些接口/泛型语法,以避免一些代码重复,以防你想要显示很多模态形式:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
但说实话,我觉得它有点过分了.
第二点:如果您的表单不完全遵循此特定行为(ShowDialog()然后设置Result属性),那么您必须编写另一个接口...等.
如果这种类型的语法(泛型,接口等)不减少写入的代码行数或复杂性或可维护性(显然我们不能说这是真的如此),那么它很漂亮无用的IMO.
编辑:
表单管理实际上取决于您的用例.
FormManager概念(或者更好:考虑如何通过减少可能打开的表单的数量来改善用户体验)通常,用于启动应用程序的表单(即关闭时停止程序的表单,即作为参数的表单Application.Run())负责其他表单.您有一个主要表单,并且多个子表单.如果你的情况真的不同,那么写一些东西可能更聪明,但这取决于你的情况.我不认为可以为表格管理的一般问题提供一般的良好答案.
老实说,如果你想要一些真正可维护的东西,尽量减少(尽可能多)可以同时显示的表格数量.在大多数情况下,多个显示的无模式窗体不能提供良好的用户体验,并且如果窗体彼此依赖,则窗体寿命管理可能是有问题的.
| 归档时间: |
|
| 查看次数: |
42859 次 |
| 最近记录: |