пользователь нетерпеливый несколько кликов по пункту меню загружает MDI дочернюю форму несколько раз - PullRequest
2 голосов
/ 25 июля 2011

Некоторые формы, которые я хочу загрузить только один раз родителем MDI. Итак, в событии click элемента menu я смотрю, содержит ли свойство родительского 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();
            }

Но если нетерпеливый пользователь быстро нажимает на пункт меню при первой загрузке формы, он может быть загружен более одного раза. Второй и третий щелчки по пункту меню запускают новую копию формы до того, как экземпляр, загруженный первым щелчком мыши, будет полностью создан.

Полагаю, я мог бы поддерживать свой собственный список имен запущенных форм и в обработчике события click элемента menu добавить имя формы в список, если его еще нет, а затем удалить его из списка в закрытой дочерней форме обработчик события. Но есть ли лучший способ?

Ответы [ 3 ]

1 голос
/ 25 июля 2011

Попробуйте этот класс:

/// <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();
       }

    }

Надеюсь, эта помощь.

0 голосов
/ 25 июля 2011

вы можете отключить пункт меню при первом нажатии непосредственно перед установкой соответствующей формы ... и при закрытии формы вы можете снова включить пункт меню ... таким образом, пользователь не сможет делать то, что вы описываете ...

0 голосов
/ 25 июля 2011

простой флаг, который вы устанавливаете, когда вызывается обработчик меню - называется что-то вроде «processingClick».Если этот флаг уже установлен, просто выйдите из обработчика.Не забудьте сбросить его на false в конце процедуры.

В качестве альтернативы вы можете поместить большую критическую секцию вокруг содержимого обработчика меню - так что, если дважды щелкнуть его подряд, второй щелчок будет ждатьпервый будет обработан.Это гарантирует, что ваш 1-й щелчок выполнит всю его обработку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...