我希望MDI Parent只加载一些表单。因此,在menuitem的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();
}
但是,如果不耐烦的用户在第一次加载表单时快速点击菜单项,则可以多次加载。在第一次单击加载的实例完全实例化之前,第二次和第三次单击菜单项将启动表单的新副本。
我想我可以维护自己的已启动表单名称列表,并在menuitem的click事件处理程序中,将表单的名称添加到列表中(如果它尚不存在),稍后将其从子表单中的列表中删除事件处理程序。但是有更好的方法吗?
答案 0 :(得分:1)
试试这堂课:
/// <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();
}
}
希望得到这个帮助。
答案 1 :(得分:0)
在调用菜单处理程序时设置的简单标志 - 称为“processingClick”。如果已设置此标志,则退出处理程序。请记住在例程结束时将其重置为false。
或者你可以在菜单处理程序的内容周围放置一个很重要的部分 - 所以如果它快速连续点击两次,第二次点击将等待第一个处理。这可以保证您的第一次点击可以完成所有处理。
答案 2 :(得分:0)
你可以在安装相应的表格之前直接点击第一次点击菜单项...然后在关闭表格时你可以重新启用菜单项......这样用户就无法按你所描述的那样做... < / p>