Как я могу сделать одну форму экземпляра (не приложение)? - PullRequest
12 голосов
/ 21 июня 2010

В моем приложении C # у меня есть диалоговое окно параметров, которое можно открыть с помощью команды меню.

Я хочу убедиться, что диалоговое окно параметров имеет только один экземпляр (пользователь не может открыть более одного окна параметров в данный момент времени), не делая его модальным.

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

Может кто-нибудь указать мне, как выполнить эти задачи?

Большое спасибо.

Ответы [ 8 ]

18 голосов
/ 21 июня 2010

Ну, самый простой способ - это иметь статическое поле, в котором хранится ссылка на отдельный экземпляр или ноль, а затем метод для его извлечения или создания нового.

Обратите внимание, что это не то же самое, что сделать его одиночным - потому что я предполагаю, что если форма закрыта, вы захотите создать новый экземпляр в следующий раз. (Альтернатива - сокрытие и повторное использование - показана в ответе СТО.) Вы можете захотеть что-то вроде этого:

public class OptionsDialog : Form
{
    private static OptionsDialog openForm = null;

    // No need for locking - you'll be doing all this on the UI thread...
    public static OptionsDialog GetInstance() 
    {
        if (openForm == null)
        {
            openForm = new OptionsDialog();
            openForm.FormClosed += delegate { openForm = null; };
        }
        return openForm;
    }
}

Вы, конечно, можете заставить метод выполнять шаги «вывести его на передний план».

10 голосов
/ 21 июня 2010

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

    protected override void OnFormClosing(FormClosingEventArgs e) {
        if (e.CloseReason == CloseReason.UserClosing) {
            this.Hide();
            e.Cancel = true;
        }
    }

Чтобы сделать его одиночным, просто следите за временем жизни формы в вашем основном классе формы:

    frmOptions options;

    private void btnShowOptions_Click(object sender, EventArgs e) {
        if (options == null) {
            options = new frmOptions();
            // To make absolutely sure:
            options.FormClosed += (o, ea) => options = null;
        }
        else {
            options.WindowState = FormWindowState.Normal;
        }
        options.Show();
    }
6 голосов
/ 21 июня 2010

Вам понадобится эта форма как свойство

Form1 myForm = null;
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
    myForm = null;
}

private void ShowForm()
{
    if (myForm != null)
    {
        myForm.BringToFront();
    }
    else
    {
        myForm = new Form1;
        myForm.Show();
    }
}
2 голосов
/ 21 июня 2010

Вы можете использовать код, подобный этому:

private MyDialogForm _FormInstance;

public void ShowOptions()
{
     if (_FormInstance == null)
     {
        _FormInstance = new MyDialogForm();
        _FormInstance.FormClosing += (s,e) => 
        {
             e.Cancel = true;
             _FormInstance.Hide();
        }
      }
     _FormInstance.Show();
}
0 голосов
/ 27 мая 2019

Это может помочь! Примечание. Следующий код взят из статьи ниже: https://www.dotnetcurry.com/ShowArticle.aspx?ID=150

static class Program
    {
        ///<summary>
        /// The main entry point for the application.
        ///</summary>
        [STAThread]
        static void Main()
        {
            bool instanceCountOne = false;

            using (Mutex mtex = new Mutex(true, "MyRunningApp", out instanceCountOne))
            {
                if (instanceCountOne)
                {
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    Application.Run(new Form1());
                    mtex.ReleaseMutex();
                }
                else
                {
                    MessageBox.Show("An application instance is already running");
                }
            }
        }
    }
0 голосов
/ 27 июня 2018
    Main_Frm _main_Frm = null;

    private void Show_bt_Click(object sender, EventArgs e)
    {

        if (_main_Frm != null)
        {
            _main_Frm .BringToFront();
        }
        else
        {
            _main_Frm = new Comission_Frm();
            _main_Frm .Show();
        }

         //This condition used when you closed the form the form will disposed and when you reopen.
        if (_main_Frm .IsDisposed)
        {
            _main_Frm = new _Main_Frm ();
            _main_Frm .Show();
        }
   }
0 голосов
/ 26 мая 2016

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

        if (this.aboutForm == null)
        {
            this.aboutForm = new AboutForm();
            this.aboutForm.FormClosed += (sender2, e2) => { this.aboutForm = null; };
            this.aboutForm.ShowDialog(this);
        }
        else
        {
            this.aboutForm.Focus();
        }

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

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

Полагаю, у вас есть как минимум две формы.Одна форма, называемая frmMain, позволяет открывать frmOptions.В frmMain добавьте переменную типа frmOptions, например:

public partial class frmMain : Form
{
     private frmOptions optionsInstance = null;
     ...

В подпрограмму, открывающую диалоговое окно «Параметры», добавьте следующее:

if (optionsInstance == null || !optionsInstance.Visible)
{
     optionsInstance = new frmOptions();
     optionsInstance.Show();
}

Когда закроется frmOptions, optionsInstance не будетnull, поэтому вы проверяете, виден ли он перед созданием экземпляра frmOptions.

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

...