Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Как правильно отобразить немодальный диалог?


Автор: ВладимирБерезин 21.10.2015, 12:24
Здравствуйте!
есть вот такой код:
Код

        private void найтиToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (rtbNotepad.Text != "") {
                SearchDialog sed = new SearchDialog();
                sed.Show();
            }
        }



Здесь, при выборе на главной форме пункта меню "Найти", выводится немодальная форма. Проблема вот в чём: при каждом клике по этому пункту меню создаётся новый экземпляр диалогового окна. Вопрос: как этого избежать?
Не хотелось бы переменную sed выносить за пределы метода найтиToolStripMenuItem_Click и делать её полем класса. Некрасиво это как-то...

Автор: Экскалупатор 21.10.2015, 20:22
почему некрасиво? если у вас логика требует одной формы то в любом случае вам нужно хранить ее в одной переменной. Можно синглтон замутить. 
Мне кажется вам не обязательно иметь именно одну форму. скорее всего вопрос в данных в этой форме. Можно их сохранить и заполнять форму сохраненными данными. тогда визуально это будет выглядеть как одна форма.

P.S.
а вот такие названия "найтиToolStripMenuItem_Click" это действительно "некрасиво".

Автор: ВладимирБерезин 22.10.2015, 08:27
Цитата(Экскалупатор @ 21.10.2015,  20:22)
Мне кажется вам не обязательно иметь именно одну форму. скорее всего вопрос в данных в этой форме. Можно их сохранить и заполнять форму сохраненными данными. тогда визуально это будет выглядеть как одна форма.


Вот тут я не очень понял. У меня диалоговое окно размножается.

Автор: Экскалупатор 22.10.2015, 10:25
Ну мысль была в том, что при клике по кнопке окно можно просто закрыть и открыть заново, только данными заполнить. Но для этого придется вынести переменную из метода. Кстати, почему это некрасиво? если есть такая логика, то по другому не получится. В любом случае придется проверить есть ли такая форма. И если есть то попытаться что то с ней сделать.

Автор: ВладимирБерезин 22.10.2015, 11:11
Вы меня убедили. В конце концов я сделал вот так:

Код

namespace MyNotePad
{
    public partial class frmNotepad : Form
    { 
       ...
       SearchDialog sed = null;
       ...
        private void найтиToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (rtbNotepad.Text != "" && sed == null) {
                sed = new SearchDialog();
                sed.Show();
                sed = null;
            }
        }
        ...
    }
}

Автор: chupachups 22.10.2015, 11:25
И что? работает?
Копни в другую сторону, смотри ниже, только я не уверен, что в качестве sender идет объект типа ToolStripMenuItem, так как не использую этот глючный контрол.
Код

namespace MyNotePad
{
    public partial class frmNotepad : Form
    {
       ...
        private void найтиToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var menuItem = (sender as ToolStripMenuItem);
            if (rtbNotepad.Text != "" && menuItem.Tag == null) 
            {
                var form = new SearchDialog();
                menuItem.Tag = form;
                form.FormClosed += delegate
                {
                    menuItem.Tag = null;
                );
                form.Show();
            }
        }
        ...
    }
}


Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Kak-pravilno-otobrazit-nemodalny-dialog-id56275a66ae20157f678b4567#findElement_E7045_56289d92ae2015866c0470a6_0

Автор: ВладимирБерезин 22.10.2015, 18:00
Цитата(chupachups @ 22.10.2015,  11:25)
И что? работает?

Работает.

Автор: Rokforus 23.10.2015, 11:08
А как оно работает в случае, если несколько раз выбрать пункт меню "Нажать" ?
Получается, код будет продолжать создавать новые экземпляры SearchDialog формы.
Из условий задачи я понял, что это нужно избегать.

Думаю, если класс SearchDialog реализовать через шаблон Singleton, то new SearchDialog() всегда будет возвращать указатель на одну и ту же форму и метод form.Show() должен будет работать с одним и тем же окном. Правда, в этом случае есть смысл дополнительно вызвать form.Activate() для перехода на форму.

Хороших выходных!


Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Kak-pravilno-otobrazit-nemodalny-dialog-id56275a66ae20157f678b4567#findElement_E7045_5629eb17ae2015c1630470ef_0

Автор: chupachups 24.10.2015, 21:34
@Rokforus, и как же может выглядеть шаблон Singleton для использования через конструктор, а не через статический метод?

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Kak-pravilno-otobrazit-nemodalny-dialog-id56275a66ae20157f678b4567#findElement_E7045_562bcf1aae201599468b46e5_0

Автор: Rokforus 26.10.2015, 01:53
Вы правы - скорее всего академический Singleton тут сложно применить.

Тем не менее я могу предложить свой рабочий вариант, который делает именно так, как я описал выше:

Код

namespace MyNotePad
{
    public partial class frmNotepad : Form
    {

        SearchDialog sed = null;

        private SearchDialog Sed
        {
            get {
                if (sed == null)
                {
                    sed = new SearchDialog();
                    sed.FormClosed += delegate
                    {
                        sed = null;
                    };
                }
                return sed;
            }
        }

        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            if (rtbNotepad.Text != "")
            {
                Sed.Show();
                Sed.Activate();
            }
        }

        ...

    }
}


Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Kak-pravilno-otobrazit-nemodalny-dialog-id56275a66ae20157f678b4567#findElement_E7045_562d5d53ae20157622886f93_0

Автор: chupachups 26.10.2015, 12:54
Сразу могу предположить что как минимум в 75% случаев понадобится писать так:
Код

Sed.Show();

if (Sed.WindowState == FormWindowState.Minimized)
   Microsoft.WinApi.User32.ShowWindow(Sed.Handle, Microsoft.WinApi.Constants.SW_RESTORE);

Sed.BringToFront();
Sed.Activate();



Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Kak-pravilno-otobrazit-nemodalny-dialog-id56275a66ae20157f678b4567#findElement_E7045_562df853ae2015ab73886f58_0

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)