用户不耐烦的多次点击菜单项加载MDI子表单多次
本文关键字:加载 MDI 表单 菜单项 不耐烦 用户 | 更新日期: 2023-09-27 18:03:42
有些表单我只想由MDI父组件加载一次。因此,在菜单项的click事件中,我查看MDI父元素的.Children属性是否已经包含表单,并且只有当窗体不在子元素中时才会加载窗体:
bool alreadyLoaded = false;
if (this.MdiChildren.Length > 0)
{
foreach (Form frm in this.MdiChildren)
{
if (frm.Name == "foo")
{
alreadyLoaded=true;
break;
}
}
}
if (! alreadyLoaded)
{
FOO f = new FOO();
f.MdiParent=this;
f.Show();
}
但是,如果不耐烦的用户在第一次加载表单时快速单击菜单项,则可以加载多次。在第一次单击加载的实例完全实例化之前,在菜单项上的第二次和第三次单击启动表单的新副本。
我想我可以维护我自己的启动表单名称列表,并在菜单项的单击事件处理程序,添加表单的名称到列表中,如果它还没有,然后从子表单的关闭事件处理程序列表中删除它。但是有没有更好的办法呢?
试试这个类:
/// <summary>
/// Displays form in mdi form once
/// </summary>
/// <autor>Saber Amani</autor>
/// <lastUpdate>2009-03-03</lastUpdate>
public class MdiFormDisplayer
{
private Hashtable fForms = new Hashtable();
private object fSender = null;
public MdiFormDisplayer(object sender)
{
fSender = sender;
}
public Form GetForm(Type formType)
{
string formName = formType.Name;
Form frm = (Form)fForms[formName];
if (frm == null || frm.IsDisposed)
{
frm = CreateNewInstance(formType);
fForms[formName] = frm;
}
return frm;
}
public Form GetForm(string formName)
{
if (fSender == null)
throw new ArgumentNullException("Sender", "Sender can't be null");
return GetForm(fSender, formName);
}
public Form GetForm(object sender, string formName)
{
Form frm = (Form)fForms[formName];
if (frm == null || frm.IsDisposed)
{
frm = CreateNewInstance(sender, formName);
fForms[formName] = frm;
}
return frm;
}
private Form CreateNewInstance(object sender, string formName)
{
Type frmType;
frmType = FindFormType(sender, formName);
Form frmInstance = (Form)CallTypeConstructor(frmType);
return frmInstance;
}
private Form CreateNewInstance(Type frmType)
{
Form frmInstance = (Form)CallTypeConstructor(frmType);
return frmInstance;
}
private Type FindFormType(object sender, string formName)
{
Type baseType = sender.GetType();
Assembly senderAssembly = Assembly.GetAssembly(baseType);
Type result = null;
// Search with assembly standard method
result = senderAssembly.GetType(baseType.Namespace + "." + formName);
if (result != null)
return result;
// Search with in the types
Type[] assemblyTypes = senderAssembly.GetTypes();
formName = formName.ToLower();
for (int i = 0; i < assemblyTypes.Length; i++)
{
if (assemblyTypes[i].Name.ToLower() == formName)
return assemblyTypes[i];
}
return null;
}
private object CallTypeConstructor(Type frmType)
{
Type[] contructTypes = new Type[] { };
ConstructorInfo constructorObj = frmType.GetConstructor(contructTypes);
object result = constructorObj.Invoke(null);
return result;
}
}
的用法如下:
public partial class frmMainForm : Form
{
MdiFormDisplayer forms;
public frmMainForm()
{
InitializeComponent();
forms = new MdiFormDisplayer(this);
}
private void btnCompany_Click(object sender, EventArgs e)
{
Form frm = forms.GetForm(typeof(frmCompany));
frm.MdiParent = this;
frm.Show();
frm.Focus();
}
}
一个简单的标志,当菜单处理程序被调用时设置——叫做类似"processingClick"的东西。如果已经设置了此标志,则退出处理程序。记住在例程结束时将其重置为false。
或者,您可以在菜单处理程序的内容周围放置一个大的临界区-因此,如果快速连续单击两次,第二次单击将等待第一次被处理。这保证了你的第一次点击可以完成所有的处理。
你可以在第一次点击时直接禁用菜单项,然后再安装相应的表单…在关闭表单时,您可以重新启用菜单项…这样用户就不能做你所描述的…