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

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

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

5 ответов


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

эти являются точными проблемами, с которыми вы столкнетесь, если вы вызовете приложение.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>
        //...
    }

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

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


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


Мне кажется, что вы можете использовать приложение 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.

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

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

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

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

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

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

на самом деле ответ очень простой. Попробуй!--2-->

newForm.showDialog();

Это откроет новую форму, в то время как родительская недоступна.