MonoWindows VistaWindows 2003Visual Studio 2005Windows 2000Windows XP.NET 2.0C# 2.0初学者开发Visual StudioWindows.NETC#
单实例表单
MDI 应用程序中的单实例表单
引言
最近在 C# 论坛上,有人问到如何确保 MDI 应用程序中某些窗体的单实例。在我的回复中,我使用了泛型和一个匿名 delegate
来创建一个稍微更通用的解决方案来解决他的问题。在他的回应中,他要求解释这些主题,并且可能撰写(这篇)文章来解释代码。
代码
所以这里是实现中的关键代码片段
private Dictionary<Type, Form> SingleInstanceForms = new Dictionary<Type, Form>();
protected Form ActivateForm<T>() where T : Form, new()
{
if (!this.SingleInstanceForms.ContainsKey(typeof(T)))
{
T newForm = new T();
// Set up the necessary properties
newForm.MdiParent = this;
newForm.FormClosed += new FormClosedEventHandler
(delegate(object sender, FormClosedEventArgs e)
{
this.SingleInstanceForms.Remove(sender.GetType());
});
this.SingleInstanceForms.Add(typeof(T), newForm);
}
Form formToActivate = this.SingleInstanceForms[typeof(T)];
formToActivate.Show();
formToActivate.Activate();
return formToActivate;
}
事实上,这就是强制执行某些窗体单实例所需的所有代码。
Using the Code
要激活(并在需要时创建)所需的窗体,您只需使用以下代码
this.ActivateForm<FormType>();
代码解释
词典
字典是代码的核心,它存储了已在 MDI 父窗口中显示的窗体实例,与其关联的键是窗体的 Type
。字典结构自动为我们提供了检查 Form
是否已先前打开的方法。
使用这种方法既有优点也有缺点。其中一个优点已经提到。 缺点是需要额外的代码来管理字典,但是当您考虑到唯一的其他解决方案是循环遍历所有现有窗体时,我认为这并不重要,并且这将花费更长的时间,具体取决于有多少窗体是打开的。 以牺牲一点内存为代价,这是一个不错的解决方案。
ActivateForm
protected Form ActivateForm<T>() where T : Form, new() { }
此方法声明使用泛型来限制传递给方法的类型,约束为 Form, new()
,即 T
必须是 Form
类型,并且必须具有默认构造函数。
该方法首先检查窗体的类型是否存在于字典中。 如果不存在,则它创建一个新的窗体实例,设置必要的属性并将其添加到字典中。
匿名委托
代码行如下
newForm.FormClosed += new FormClosedEventHandler
(delegate(object sender, FormClosedEventArgs e)
{
this.SingleInstanceForms.Remove(sender.GetType());
});
可以将其重写为如下形式
newForm.FormClosed += new FormClosedEventHandler(this.MdiChild_FormClosed);
private void MdiChild_FormClosed(object sender, EventArgs e)
{
this.SingleInstanceForms.Remove(sender.GetType());
}
Web 上有很多关于匿名 delegate
的优秀解释,因此我不会尝试解释它们。 但是,使用 delegate
而不是单独方法的原因是它使 ActivateForm
方法更紧凑,即在源代码视图中,而不是生成的 IL 中。
历史
- 2007 年 9 月 9 日:首次发布