用户不耐烦的多次点击菜单项加载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();
            }

但是,如果不耐烦的用户在第一次加载表单时快速单击菜单项,则可以加载多次。在第一次单击加载的实例完全实例化之前,在菜单项上的第二次和第三次单击启动表单的新副本。

我想我可以维护我自己的启动表单名称列表,并在菜单项的单击事件处理程序,添加表单的名称到列表中,如果它还没有,然后从子表单的关闭事件处理程序列表中删除它。但是有没有更好的办法呢?

用户不耐烦的多次点击菜单项加载MDI子表单多次

试试这个类:

/// <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。

或者,您可以在菜单处理程序的内容周围放置一个大的临界区-因此,如果快速连续单击两次,第二次单击将等待第一次被处理。这保证了你的第一次点击可以完成所有的处理。

你可以在第一次点击时直接禁用菜单项,然后再安装相应的表单…在关闭表单时,您可以重新启用菜单项…这样用户就不能做你所描述的…