Как избежать дублирования создания форм в .NET Windows Forms? - PullRequest
4 голосов
/ 11 июня 2010

Я использую .NET Windows Forms. Моя родительская форма MDI содержит меню. Если щелкнуть меню, появится форма. До сих пор никаких проблем.

UserForm uf = new UserForm();
uf.Show();
uf.MdiParent = this;

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

Ответы [ 8 ]

5 голосов
/ 11 июня 2010

Самый простой способ - просто отслеживать время жизни экземпляра формы. Сделайте это, подписавшись на событие FormClosed. Например:

    private UserForm userFormInstance;

    private void showUserForm_Click(object sender, EventArgs e) {
        if (userFormInstance != null) {
            userFormInstance.WindowState = FormWindowState.Normal;
            userFormInstance.Focus();
        }
        else {
            userFormInstance = new UserForm();
            userFormInstance.MdiParent = this;
            userFormInstance.FormClosed += (o, ea) => userFormInstance = null;
            userFormInstance.Show();
        }
    }
4 голосов
/ 11 июня 2010

В отличие от существующих здесь ответов, я бы не рекомендовал бы использовать для этого Singleton. Шаблон Singleton ужасно используется и, как правило, является «запахом кода», который указывает, что что-то пошло не так с вашим общим дизайном. Синглтоны обычно помещаются в то же «ведро», что и глобальные переменные: вам лучше иметь действительно веские аргументы для их использования.

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

public class MainMdiForm : Form
{
    ...

    UserForm userForm;

    ...

    private void ShowUserForm()
    {
        if(userForm == null || userForm.IsDisposed)
        {
            userForm = new UserForm();
            userForm.MdiParent = this;
        }

        userForm.Show();
        userForm.BringToFront();
    }
}
4 голосов
/ 11 июня 2010

Вы должны создать класс singleton для управления экземплярами формы:

public class FormProvider
{
   public static UserForm UserForm
   {
       get
       {
          if (_userForm== null || _userForm.IsDisposed)
          {
            _userForm= new UserForm ();
          }
          return _userForm;
       }
   }
   private static UserForm _userForm;
}

Примечание: это очень простой шаблон Singleton.Чтобы правильно использовать шаблон, используйте эту ссылку .

. Вы можете просто получить доступ к форме следующим образом:

FormProvider.UserForm.Show();
FormProvider.UserForm.MdiParent = this;

Когда FormProvider.UserForm Доступ в первый раз, он будет создан.Любое последующее получение свойства FormProvider.UserForm вернет форму, созданную при первом доступе.Это означает, что форма будет создана только один раз.

3 голосов
/ 15 января 2013

Если вы знаете название формы:

    if (Application.OpenForms["FormName"] == null)
       {
           Form form = new Form();
           form.MdiParent = this;
           form.Show();
       }
       else
           Application.OpenForms["FormName"].Focus(); 
0 голосов
/ 28 апреля 2013

Это мое решение в ShowForm () и вызов образца в aboutToolStripMenuItem_Click ():

    private void ShowForm(Type typeofForm, string sCaption)
    {
        Form fOpen = GetOpenForm(typeofForm);
        Form fNew = fOpen;
        if (fNew == null)
            fNew = (Form)CreateNewInstanceOfType(typeofForm);
        else
            if (fNew.IsDisposed)
                fNew = (Form)CreateNewInstanceOfType(typeofForm);

        if (fOpen == null)
        {
            fNew.Text = sCaption;
            fNew.ControlBox = true;
            fNew.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
            fNew.MaximizeBox = false;
            fNew.MinimizeBox = false;
            // for MdiParent
            //if (f1.MdiParent == null)
            //    f1.MdiParent = CProject.mFMain;
            fNew.StartPosition = FormStartPosition.Manual;
            fNew.Left = 0;
            fNew.Top = 0;
            ShowMsg("Ready");
        }
        fNew.Show();
        fNew.Focus();
    }
    private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
    {
        ShowForm(typeof(FAboutBox), "About");
    }

    private Form GetOpenForm(Type typeofForm)
    {
        FormCollection fc = Application.OpenForms;
        foreach (Form f1 in fc)
            if (f1.GetType() == typeofForm)
                return f1;

        return null;
    }
    private object CreateNewInstanceOfType(Type typeofAny)
    {
        return Activator.CreateInstance(typeofAny);
    }

    public void ShowMsg(string sMsg)
    {
        lblStatus.Text = sMsg;
        if (lblStatus.ForeColor != SystemColors.ControlText)
            lblStatus.ForeColor = SystemColors.ControlText;
    }
    public void ShowError(string sMsg)
    {
        lblStatus.Text = sMsg;
        if (lblStatus.ForeColor != Color.Red)
            lblStatus.ForeColor = Color.Red;
    }
0 голосов
/ 11 июня 2010

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

UserForm myForm = null;
foreach (Form existingForm in this.MdiChildren)
{
    myForm = existingForm as UserForm;
    if (myForm != null)
        break;
}

if (myForm == null)
{
    myForm = new UserForm();
    myForm.MdiParent = this;

    myForm.Show();
}
else
    myForm.Activate();

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

0 голосов
/ 11 июня 2010

Опции:

Как правило, отключение кнопки работает нормально и имеет больше смысла с точки зрения пользователя.Синглтон работает, если вам нужна кнопка для чего-то другого.

Синглтон, вероятно, не хорошее решение, если форма может быть закрыта и позже потребуется новый экземпляр.

0 голосов
/ 11 июня 2010

Вы всегда можете сделать форму синглтоном:

public class MyForm : Form
{
    private MyForm _instance = null;
    private object _lock = new object();

    private MyForm() { }


    public static MyForm Instance
    {
        get
        {
            if (_instance == null)
            {
                lock (_lock)
                {
                    if (_instance == null)
                    _instance = new MyForm();
                }
            }
            return _instance;
        }
    }
}

Тогда ваш вызов будет выглядеть примерно так:

MyForm.Instance.Show();
MyForm.Instance.MdiParent = this;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...