WinForms programming - Modal and Non-Modal forms problem

六眼飞鱼酱① 提交于 2019-11-29 04:36:56

Modal forms do exactly what "modal" means, they disable all other windows in the app. That's rather important, your program is in a somewhat perilous state. You've got a chunk of code that is waiting for the dialog to close. Really Bad Things could happen if those other windows were not disabled. Like the user could start the modal dialog again, now your code is nested twice. Or she could close the owner window of the dialog, now it suddenly disappears.

These are the exact kind of problems you'd run into if you call Application.DoEvents() inside a loop. Which is one way to get a form to behave modal without disabling other windows. For example:

    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();
    }

This is dangerous.

It is certainly best to use modal forms the way they were designed to stay out of trouble. If you don't want a modal form then simply don't make it modal, use the Show() method. Subscribe to its FormClosing event to know that it is about to close:

    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>
        //...
    }

The first thing that comes to mind would be something like this. You could disable form 1 when you launch form 2 and then have form 1 handle the closed event of the second form to re-enable itself. You would NOT open modal 2 using show dialog.

Now keep in mind, from a user perspective this is going to be quite cumbersome, you might look at doing a MDI application to get all windows inside of a single container.

Your main form will not be responsive until any modal dialogs that are in the same process space are closed. There is not work around for that.

It looks to me like you could use an MDI application setting the Form #0 IsMdiContainer property to true.

Then, you could do something alike:

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();
    }
}

Using the ShowDialog() as you stated in your question will make all of the forms Modal = true.

By definition, a modal form is:

When a form is displayed modally, no input (keyboard or mouse click) can occur except to objects on the modal form. The program must hide or close a modal form (usually in response to some user action) before input to another form can occur. Forms that are displayed modally are typically used as dialog boxes in an application.

You can use this property [(Modal)] to determine whether a form that you have obtained from a method or property has been displayed modally.

So, a modal form shall be used only when you require immediate assistance/interaction from the user. Using modal forms otherwise makes believe that you're perhaps running into a wrong direction.

If you do not want your main form to be an MDI container, then perhaps using multithreading is one solution through a simple BackgroundWorker class is the key to what you want to achieve. Thus, it looks to me like a design smell...

  • What is it you want to do, apart of making your main form responsive, etc.
  • What is it you have to do?

Explaining what you have to do, we might be able to guide you altogether into the right, or at least perhaps better, direction.

Actually the answer is very simple. Try

newForm.showDialog();

This will open a new form, while the parent one is inaccessible.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!