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: