Modal and Modeless Forms/Dialogs

 

Dialogs are created as forms in .Net. You can simply add another form to the current project by right clicking on the project name in Visual Studio.Net, then picking an “Add New Item…” to be a “Windows Form” type. Once the user interface of the added form has been designed properly, you can display this form from a parent form in a “modal” or “modeless” manner. If a form is displayed in a modal manner, the parent program cannot continue beyond the statemenet that displays the modal form unless the modal form is terminated. The modal form can communicate the actual reason for termination to the parent form through the DialogResult property which can take on one of the values from the DialogResult enumeration. Any additional information that needs to be communicated to the parent form of the modal form can be done by setting the data members or properties of the modal form prior to its termination. The parent form can then examine these data members or properties after the modal dialog has been terminated.

 

Example of a Modal Form:

            Create a C# windows form type application called “ModalModeless” in VS.Net. Add a button in the main form (Form1) with a name of “btnShowLogin” and a text property of “Show Login Dialog”. By right clicking on the project, add another form to the project (Add->Add New Item..). Name this form “LoginDlg.cs”. Put two labels, two text boxes and two buttons in this Login dialog, as shown below.

 

 

Name the textboxes as “txtUsername” and “txtPassword” respectively. Set the password character to * for the password text box. Name the first button as “btnLogin”, the second button as “btnCancel”. Since the parent form will need to know the user name and the password entered in the login dialog, you need to add two properties in the LoginDlg class (LoginDlg.cs file) as shown below. Note that, you only are writing the get method for the properties as the parent form will be only reading the data entered by the user.

 

            public class LoginDlg : System.Windows.Forms.Form

            {

                        private string uname;

                        public string Uname

                        {

                                    get { return uname; }

                        }

                        private string pw;

                        public string PW

                        {

                                    get { return pw; }

                        }

                        private System.Windows.Forms.TextBox txtUsername;

                        ….

 

The code for the “Login” and “Cancel” button handlers in the LoginDlg is shown below.

                        private void btnLogin_Click(object sender, System.EventArgs e)

                        {

                                    this.uname = txtUsername.Text;

                                    this.pw = txtPawword.text;

                                    this.DialogResult = DialogResult.OK; // also closes the dialog

                        }

 

                        private void btnCancel_Click(object sender, System.EventArgs e)

                        {

                                    this.DialogResult = DialogResult.Cancel; // also closes the dialog

                        }

 

Back to Form1. Write the following handler for the “Show Login Dialog” button.

                        private void btnShowLogin_Click(object sender, System.EventArgs e)

                        {

                                    LoginDlg ldg = new LoginDlg();

                                    if (ldg.ShowDialog() == DialogResult.OK)

                                    {

                                                string unm = ldg.Uname;

                                                string pw = ldg.PW;

                                                if ((unm == "windows") && (pw == "cs440"))

                                                            MessageBox.Show("Correct login");

                                                else

                                                            MessageBox.Show("Incorrect login");

                                    }

 

Build and test the application.

 

Modeless Forms:

            Modeless forms coexist with the parent application. The call to display a modeless form is Show( ). When the user makes a change to the modeless form e.g., clicks a button, we need to invoke an event handler in the parent form. This can be easily handled by passing a delegate (that points to a member function in the parent form) to the constructor in the child form. The constructor’s code can then set it for a local button.

 

Example:

            Add another form to the “ModalModeless” project. Name this form “MsgDlg.cs”. Design the user interface in this dialog as shown below.

 

Name the textbox as “txtMsg”. The two buttons are named as “btnSendMsg” and btnClose”. Add a property called msg in the MsgDlg class as shown below.

                        public string Msg

                        {

                                    get { return txtMsg.Text; }

                        }

 

Add another constructor to the MsgDlg.cs class as shown below.

            public MsgDlg(System.EventHandler del)

            {

                        InitializeComponent();

                        this.btnSendMsg.Click += del; 

                                    // set the delegate to a func. in parent form

            }

 

Write the following code for the “Close” button handler in the MsgDlg class.

            private void btnClose_Click(object sender, System.EventArgs e)

            {

                        this.Close();

            }

 

The above function sets the click event handler for the “send Message” button to a function in the parent form. This way whenever the user clicks on this button, it can invoke a function in the parent form which can then read the Msg property to find out what message is being sent by the child form.

 

Now we need to add the “Send Message” button handler in the parent form. To do this, type the following code in the Form1 class.

            private void GetChildMessage(object sender, System.EventArgs e)

                        {

                                    MessageBox.Show(mdlg.Msg);

                        }

 

Add the following declaration in the beginning of the Form1 class.

private MsgDlg mdlg;  // child modeless dialog

 

 

Now add a button to the Form1 class. Name the button “btnShowMsgDlg”. Give it a text property of “Show Message Dialog”. Type the following code in the “Show Message Dialog” handler.

 

         private void btnShowMsgDlg_Click(object sender, System.EventArgs e)

         {

              System.EventHandler pDel = new System.EventHandler(this.GetChildMessage);

                                    // delegate to GetChildMessage

              mdlg = new MsgDlg(pDel);

              mdlg.Show();

         }

 

Build and test the application.

        

 

 

Passing Parent Form to the Child Form:

Another way to design the above modeless example would be to pass the entire parent form (Form1in above example) to the constructor in the child form (MsgDlg). The constructor of the child form will then set the delegate to its “Send Message” button to one of the functions in the parent form by using the following code.

 

                        public MsgDlg(Form1 fm)

                        {

                                    InitializeComponent();

                                    this.btnSendMsg.Click +=

                                                new System.EventHandler(fm.GetChildMessage); 

                                    // set the delegate to a func. in parent form

                        }

 

To accomplish the above, you will need to change the private attribute of “GetChildMessage” function in Form1 to public.

 

The code in the parent form that invokes the child form in a modeless manner (“Show Message Dialog” handler) will now look as:

 

         private void btnShowMsgDlg_Click(object sender, System.EventArgs e)

         {

              mdlg = new MsgDlg(this);  // sending parent form to child

              mdlg.Show();

         }

 

If you build and test the application. It should function as before.

 

 

MessageBox as a Modal Dialog and Closing Event:

            In addition to displaying messages to the user in a modal manner, a MessageBox can be used to collect simple information from the user. It is capable of displaying several buttons to the user defined by the MessageBoxButtons enumeration. It can also show different kinds of icons in the messagebox. These icons are defined by the MessageBoxIcon enumeration. As an example, one use of such message box can be in closing an application. When some one x’s the main form of an application, we may want to ask the user if he or she will really like to close the application or not. The solution is to write the Form_Closing event handler and ask the user via a MessageBox. If the user cancels the closing of the the main application, then you should set the Cancel property of the form to true to avoid terminating the application.

 

Example: Add a closing event handler to the Form1 in the above application. Write the following code in it.

    private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)

         {

              DialogResult d1 = MessageBox.Show("OK to quit", "terminate?",MessageBoxButtons.OKCancel,MessageBoxIcon.Question);

              if (d1 == DialogResult.Cancel)

                  e.Cancel = true;

         }

 

Now when you try to x out the application, you will get the above confirmation dialog. If you choose cancel, the program will not terminate.

 

Common Dialogs: