Part #1
Building Windows Forms Applications With C#
Implementing an MDI Form
The Multiple-Document Interface (MDI) is a specification that defines a user
interface for applications that enable the user to work with more than one
document at the same time under one parent form (window).
Visualize the working style of an application in which you are allowed to open multiple
forms in one parent container window, and all the open forms will get listed under the
Windows menu. Whereas
having an individual window for each instance of the same application is termed
as single document interface (SDI); applications such as Notepad, Microsoft Paint,
Calculator, and so on, are SDI applications. SDI applications get opened only in
their own windows and can become difficult to manage, unlike when you have
multiple documents or forms open inside one MDI interface.
Hence, MDI applications follow a parent form and child form relationship model.
MDI applications allow you to open, organize, and work with multiple documents
at the same time by opening them under the context of the MDI parent form;
therefore, once opened, they can't be dragged out of it like an individual form.
The parent (MDI) form organizes and arranges all the child forms or documents
that are currently open. You might have seen such options in many Windows
applications under a Windows menu, such as Cascade, Tile Vertical, and so on.
Try It: Creating an MDI Parent Form with a Menu Bar
In this exercise, you will create an MDI form in the WinApp project. You will
also see how to create a menu bar for the parent form, that will allow you to
navigate to all the child forms. To do so, follow these steps:
- Navigate to Solution Explorer, select the WinApp project, right-click, and select "Add" -> "Windows form". Change the Name value from "Form1.cs" to "ParentForm.cs", and click "Add".
- Select the newly added ParentForm in the Design View. Select the ParentForm form by clicking the form's title bar, navigate to the Properties window, and set the following properties:
- Set the "IsMdiContainer" property to True (the default value is False). Notice that the background color of the form has changed to dark gray.
- Set the Size property's Width to 546 and Height to 411.
- Drag a MenuStrip control to the ParentForm. In the top-left corner, you should now see a drop-down showing the text "Type Here". Enter the text "Open Forms" in the drop-down. This will be your main, top-level menu.
- Now under the Open Forms menu, add a submenu by entering the text "Win App".
- Under the Win App submenu, enter "User Info".
- Now click the top menu, "Open Forms", and on the right side of it, type "Help". Under the Help menu, enter "Exit".
- Now, click the top menu, on the right side of Help, type "Windows".
- Under the Windows menu, add the following options as separate submenus: Cascade, Tile Horizontal, Tile Vertical, and Arrange Icons. These will help in arranging the child forms.
- Now it's time to attach code to the submenus you have added under the main menu Open Forms. First, you'll add code for the submenu Win App, that basically will open the WinApp form. In the Design View, double-click the "Win App" submenu, that will take you to the Code View. Under the click event, add the following code:
WinApp objWA = new WinApp();
objWA.Show();
- Now to associate functionality with the User Info submenu: double-click this submenu, and under the click event add the following code:
UserInfo objUI = new UserInfo();
objUI.Show();
- To associate functionality with the Exit submenu located under the Help main menu, double-click "Exit", and under the click event add the following code:
Application.Exit();
- Now you have the form-opening code functionality in place, and you are nearly set to run the application. But first, you need to set the ParentForm as the start-up object. To do so, open Program.cs, and modify the "Application.Run(new UserInfo());" statement to the following:
Application.Run(new ParentForm());
- Now build the solution, and run the application by pressing F5; the MDI application will open and should look as in Figure 1-1.
Figure 1-1. Running an MDI form application
- Now if you click "Win App" and then "User Info" then both the forms will open one by one. These forms can be opened and dragged outside of the MDI form. This is not an expected behavior from a MDI application, as shown in Figure 1-2.
This issue will be addressed later in this chapter.
Figure 1-2. Running an MDI form application
How It Works
Each Windows Forms form is a class and exposes a Show() function by an instance
created for it. You use the following code, that is creating an object and then
invoking the Show() method. This opens the other form from the MDI parent form.
This creates an instance of the WinApp form and opens it for you:
WinApp objWA = new WinApp();
objWA.Show();
The following code creates an instance of the UserInfo form and opens it for
you:
UserInfo objUI = new UserInfo();
objUI.Show();
You close the application with the following code:
Application.Exit();
Try It: Opening an MDI Child Form Within an MDI Application
As mentioned and shown in Figure 1-2 above, the problem is that even though the
MDI form shows a parent menu, the forms are still able to open outside, and
context is moved from a form to another. You can try clicking the title bar of
each the open form, and you will see how you can move back and forth with these
opened forms.
In this exercise, you will overcome this problem and associate all the forms you
created earlier as MDI child forms to the main MDI parent form you created in
the previous task.
- In the project you modified in the previous exercise, you'll first make the WinApp form an MDI child form. To do so, you need to set the MdiParent property of the child form's object to the MDI parent form itself, but in the Code View. You have already added functionality in the previous task (opening the WinApp form); just before the line where you are calling the Show() method, add the following code (this code can be found under Win App menu click event):
objWA.MdiParent=this;
After adding this line, the code will appear as follows:
WinApp objWA = new WinApp();
objWA.MdiParent = this;
objWA.Show();
Note: this is a C# language keyword that represents the current instance of the class. In this case, it refers to ParentForm. Because you are writing this code inside ParentForm, you can use the this keyword for the same.
Now you will make the UserInfo form an MDI child form. To do so, you need to set the MdiParent property to the name of the MDI parent form but in the Code View. Add the following code as you did in the previous step (this code can be found under the User Info menu click event):
objUI.MdiParent=this;
After adding this line, the code will appear as follows:
UserInfo objUI = new UserInfo();
objUI.MdiParent=this;
objUI.Show();
Now build the solution, and run the application by pressing F5; the MDI application will open and should appear as shown in Figure 1-3.
Click "Open Form" -> "Win App"; the WinApp form should open. Again, open the main menu and click "User Info". Both the forms should now be open inside your main MDI parent form application, and unlike before, you will not be able to drag these out of your MDI parent form (as shown in Figure 1-2). Figure 1-3 shows the expected behavior of an MDI application with opened form(s).
Figure 1-3. Opening child forms inside an MDI form application:
Because both the forms are open inside one MDI parent, it becomes easier to work with them, and they are not draggable outside of the MDI parent. Switch among these forms by clicking their title bars. Once you are done with the forms, close the application by selecting "Help" -> "Exit".
How It Works
As you noticed in an earlier exercise, the only issue discussed was that child
forms opened and were able to be dragged outside. In other words, they didn't
really belong to a parent form. An MDI application is about claiming a form with
a menu bar as an MDI parent so all the child forms can open inside it.
To do so, first an object of the child form needs to be created:
WinApp objWA = new WinApp();
But before we really invoke the Show() method on the objWA, you need to tell the
object who is its parent so it operates from within the MDI parent form. To
accomplish this, you will use the "this" keyword, that represents the current
form class.
objWA.MdiParent = this;
You have an object created and its context set to a MDI parent form, so now it's
a perfect time to call the Show() method, that will launch the form so you can
work with it.
objWA.Show();
The "wa.MdiParent=this;" line tells the child form which form is its parent.
Because you want all the child forms to appear inside ParentForm and you write
the code inside the MDI parent form, you can use the "this" keyword to represent
the current object.
Set the previous suggested changes for UserInfo as well.
UserInfo objUI = new UserInfo();
objUI.MdiParent=this;
objUI.Show();
Try It: Arranging MDI Child Forms Within an MDI Application
Multiple forms will open within one MDI window, so once you have a few open,
your MDI application will be cluttered. It's hard to move forms around to shift
your focus from one to another. Hence, it is a prime concern to have a mechanism
that allows you to arrange the forms in an organized manner.
For example, in most applications you can arrange the forms and then cascade
them so you can see the stack of open forms. Or you can tile them vertically or
horizontally so you can see multiple forms side by side. You can even minimize
all the open forms and arrange them as an icon.
To accomplish this, in this exercise you will add the Windows menu as shown in
Figure 1-4.
Figure 1-4. Windows menu of MDI form application to arrange child forms
.NET's Windows Forms offers the LayoutMdi method, that takes the MdiLayout
enumeration to rearrange the child forms in an MDI parent form. There are four
modes you can arrange your forms into: Cascade, Tile Horizontal, Tile Vertical,
and ArrangeIcons.
- Open the ParentForm in the Design View, and click the Windows menu, as shown in Figure 1-4.
- Double-click the first option, Cascade, under Windows, and it will take you to its click event. Add the following code:
LayoutMdi(MdiLayout.Cascade);
- Double-click Tile Horizontal, and in the Code View under the click event, add the following code:
LayoutMdi(MdiLayout.TileHorizontal);
- Double-click the Tile Vertical, and in the Code View under the click event, add the following code:
LayoutMdi(MdiLayout.TileVertical);
- Double-click Tile Vertical, and in the Code View under the click event, add the following code:
LayoutMdi(MdiLayout.ArrangeIcons);
- Now build the solution, and run the application by pressing F5; the MDI application will open. After it opens, go to the Open Forms menu and click Win App and User Info one by one. It is important to have at least two forms open in the MDI parent form. Now go to the Windows menu and try the available options by clicking Cascade, then Arrange Vertical, then Arrange Horizontal, and finally Arrange Icons. When you will try these options, Tile Vertical will show the child forms arranged as in Figure 1-5.
Figure 1-5. Arranging (Tile Vertical) child forms in the MDI form application