Программирование WinForms - Модальная и Немодальная проблема форм

У меня есть проблема с модальностью форм под C#.NET. Скажем, у меня есть основная форма № 0 (см. изображение ниже). Эта форма представляет форму главного приложения, где пользователь может выполнить различные операции. Однако время от времени существует потребность открыть дополнительную немодальную форму для выполнения дополнительных задач поддержки функциональности главного приложения. Скажем, это - форма № 1 в изображении. На этой форме № 1 там мог бы быть открыт немного дополнительных модальных форм друг на друге (#2 форма в изображении), и в конце, существует диалоговое окно прогресса показ долгого операционного прогресса и состояния, которое могло бы занять с нескольких минут несколько часов. Проблема состоит в том, что основная форма № 0 не является быстро реагирующей, пока Вы не закрываете все модальные формы (#2 в изображении). Мне нужно это, основная форма № 0 была бы операционной в этой ситуации. Однако при открытии немодальной формы в форме № 2 можно действовать и с модальной формой № 2 и с недавно созданный не модальная форма. Мне нужно то же поведение между основной формой № 0 и формой № 1 со всеми его дочерними формами. Действительно ли это возможно? Или я делаю что-то не так? Возможно, существует некоторое обходное решение, я действительно не хотел бы изменять все вызовы ShowDialog для Показа...

Изображение http://img225.imageshack.us/img225/1075/modalnonmodalproblem.png

5
задан Povilas 22 September 2011 в 07:52
поделиться

4 ответа

Модальные формы делают именно то, что означает «модальный», они отключают все другие окна в приложении. Это довольно важно, ваша программа находится в несколько обременивом состоянии. У вас есть фрагмент кода, который ожидает закрытия диалогового окна. Действительно плохие вещи могут произойти, если эти другие окна не будут отключены.Подобно тем, как пользователь может снова запустить модальное диалоговое окно, теперь ваш код вложен дважды. Или она может закрыть окно владельца диалога, теперь оно внезапно исчезает.

Это именно те проблемы, с которыми вы столкнетесь, если вызовете Application.DoEvents() внутри цикла. Это один из способов получить форму для модального поведения без отключения других окон. Например:

    Form2 mDialog;

    private void button1_Click(object sender, EventArgs e) {
        mDialog = new Form2();
        mDialog.FormClosed += (o, ea) => mDialog = null;
        mDialog.Show(this);
        while (mDialog != null) Application.DoEvents();
    }

Это опасно.

Конечно, лучше всего использовать модальные формы так, как они были разработаны, чтобы извлечь из неприятностей. Если вам не нужна модальная форма, то просто не делайте ее модальной, используйте метод Show(). Подпишитесь на его событие FormClosing, чтобы знать, что оно вот-вот закроется:

    private void button1_Click(object sender, EventArgs e) {
        var frm = new Form2();
        frm.FormClosing += new FormClosingEventHandler(frm_FormClosing);
        frm.Show();
    }

    void frm_FormClosing(object sender, FormClosingEventArgs e) {
        var frm = sender as Form2;
        // Do something with <frm>
        //...
    }
12
ответ дан 18 December 2019 в 13:11
поделиться

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

0
ответ дан 18 December 2019 в 13:11
поделиться

Первое, что приходит в голову, это что-то вроде этого. Вы можете отключить форму 1 при запуске формы 2, а затем заставить форму 1 обрабатывать закрытое событие второй формы для повторного включения. Вы НЕ открываете модальное окно 2, используя диалог отображения.

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

3
ответ дан 18 December 2019 в 13:11
поделиться

Мне кажется, вы могли бы использовать приложение MDI, устанавливающее форму № 0 IsMdiContainer значение true.

Затем вы можете сделать что-то подобное:

public partial class Form0 {
    public Form0 {
        InitializeComponent();
        this.IsMdiContainer = true; // This will allow the Form #0 to be responsive while other forms are opened.
    }

    private void button1_Click(object sender, EventArgs e) {
        Form1 newForm1 = new Form1();
        newForm1.Parent = this;
        newForm1.Show();
    }
}

Использование ShowDialog () , как вы указали в своем вопросе, сделает все формы Modal = true .

По определению, модальная форма:

Когда форма отображается модально, никакой ввод (клавиатура или щелчок мышью) не может происходить, кроме как для объектов в модальной форме. Программа должна скрыть или закрыть модальную форму (обычно в ответ на какое-либо действие пользователя), прежде чем может произойти ввод в другую форму. Формы, которые отображаются модально, обычно используются в качестве диалоговых окон в приложении.

Вы можете использовать это свойство [( Modal )], чтобы определить, отображалась ли форма, полученная вами из метода или свойства, модально.

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

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

  • Что вы хотите сделать, кроме того, чтобы сделать вашу главную форму адаптивной и т. Д.
  • Что вы должны сделать?

Объяснение того, что вы должны сделать, мы могли бы в целом направить вас в правильном или, по крайней мере, возможно лучшем направлении.

0
ответ дан 18 December 2019 в 13:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: