Walkthrough: Switching Windows Forms Menu Structures Based on Application State
It is possible to have many MainMenu objects, each of which presents different menu choices to the user. By having a number of MainMenu objects to present the correct menu structure to the user, you can handle the varying states of your application as users interact with it.
In this procedure, you will create a menu structure for when the application first opens and there is no file or data for the user to interact with. Thus, the application will have only a traditional File menu with New, Open, and Exit commands. When the user selects either the New or Open menu item, it triggers a change in application state (for demonstration purposes in the following example, a message box is shown as a visual aid; no actual files are opened or created). At this point, a second menu structure is shown, with additional menu items (Close and Save) that target an application that has data or a file loaded.
Creating a Menu at Design Time
In the following steps, you will design a Windows application, in the Windows Forms Designer, that switches menu structures.
To create a menu at design time
1. Drag a MainMenu component from the Toolbox to the form.
2. In the Menu Designer, create a top-level menu item with the Text property set to &File, and three submenu items with the Text properties set to &New, &Open, and E&xit, in that order. For details, see Adding Menus and Menu Items to Windows Forms.
3. In the Windows Forms Designer, click the form (Form1.vb, Form1.cs, or Form1.h) to give it focus. In the Properties window, ensure that the Menu property is set to the menu you have just created (MainMenu1 in Visual Basic or mainMenu1 in Visual C# or Visual C++, unless you have given it a unique name).
To hook up the events
1. Create a multicast event handler called MenuSelect for the New and Open menu items. You need to add references to the event handler in the form initialization function for Visual C# or Visual C++.
2. // C#
3. menuItem2.Click += new System.EventHandler(this.MenuSelect);
4. menuItem3.Click += new System.EventHandler(this.MenuSelect);
5.
6. // C++
7. menuItem2->Click += new System::EventHandler(this, MenuSelect);
menuItem3->Click += new System::EventHandler(this, MenuSelect);
This is a multicast event handler because it will handle the Click events for both menu items. For details, see Connecting Multiple Events to a Single Event Handler in Windows Forms.
8. Enter the following code in the MenuSelect event handler:
9. ' Visual Basic
10. Private Sub MenuSelect(ByVal sender As Object, ByVal e As System.EventArgs) Handles MenuItem2.Click, MenuItem3.Click
11. MessageBox.Show("A file has been opened.", "Instead of a new file, here's a message box.")
12. LoadSecondMenu()
13. End Sub
14.
15. // C#
16. private void MenuSelect(object sender, System.EventArgs e)
17. {
18. MessageBox.Show("A file has been opened.",
19. "Instead of a new file, here's a message box.");
20. LoadSecondMenu();
21. }
22.
23. // C++
24. private:
25. System::Void MenuSelect(System::Object * sender,
26. System::EventArgs * e)
27. {
28. MessageBox::Show("A file has been opened.",
29. "Instead of a new file, here's a message box.");
30. LoadSecondMenu();
}
Note LoadSecondMenu will be a procedure you write to switch the menu when either of the menu items (New or Open) is clicked.
31. In the Code Editor, create a method, similar to the following, to set the form's menu to the second MainMenu component you created:
32. ' Visual Basic
33. Private Sub LoadSecondMenu()
34. Me.Menu = MainMenu2
35. End Sub
36.
37. // C#
38. private void LoadSecondMenu(){
39. this.Menu = mainMenu2;
40. }
41.
42. // C++
43. private:
44. System::Void LoadSecondMenu()
45. {
46. this->Menu = mainMenu2;
}
Note MainMenu2 refers to a MainMenu component that you add to the form later on.
To copy the menus for the second set
1. In Solution Explorer, right-click the form name and choose View Designer on the shortcut menu.
2. In the component tray, click the icon for the MainMenu component, so that it has focus in the form.
3. In the Menu Designer, click the top-level menu item you created (File). Right-click and choose Copy.
Note This makes a copy of the top-level menu item and all of its submenu items.
4. Drag another MainMenu component from the Toolbox to the form.
5. In the Menu Designer, right-click the "Type Here" area and choose Paste.
The menu items you previously selected from the first MainMenu component are pasted into the second.
6. In the Menu Designer, right-click the area to the left of the Exit menu item and choose Insert New. Do this again, so that you have inserted two new menu items.
7. Set the Text property of these two new menu items to &Close and &Save, in that order, either in the Properties window or by clicking the item and typing in the space provided.
To test the application
• Debug the application and press F5 to run it. For details about debugging, see Debugging Basics.
The form has a menu that contains File, New, Open, and Exit menu items. Clicking New or Open raises an event, which is handled by the MenuSelect event handler. This method shows a message box and changes the application state. The application state change is indicated by the addition of two menu items, Close and Save.
Instead of using the above procedure, you can create the entire application in code. While this forgoes the ease of using the Windows Forms Designer, some developers may find this method more appealing.
Creating a Menu Programmatically
In the following steps, you will design a Windows application, the same as the one above, exclusively in code that switches menu structures.
To create a menu programmatically
• In a method, create an instance of the MainMenu component with MenuItem objects corresponding to the application state.
The following example has one MainMenu object for when the user first opens the application; it has only a traditional File menu with New, Open, and Exit commands. Additionally, the code below uses an overloaded Add method that creates menu items and associated event handlers with them. Wiring event handlers dynamically is an easy way to signal to the application that clicking either the New or Open menu command should trigger a change in the application state.
' Visual Basic
' Create a MainMenu object and a MenuItem object.
Private mmAppStart as MainMenu
Private miFile as MenuItem
Public Sub AppStartMenu()
' Create an instance of the MainMenu object.
mmAppStart = new MainMenu
' Create a top-level menu item and two menu items. Use this
' overloaded constructor that takes an event handler
' (MenuSelect) so that later, you can cause the menu selection
' to change the application state.
miFile = New MenuItem("&File", New System.EventHandler (AddressOf Me.MenuSelect))
miFile.MenuItems.Add("&New", New System.EventHandler (AddressOf Me.MenuSelect))
miFile.MenuItems.Add("&Open", New System.EventHandler (AddressOf Me.MenuSelect))
miFile.MenuItems.Add("&Exit")
' Add the top-level menu item to the MainMenu component
' and set the MainMenu component to be the form's menu.
mmAppStart.MenuItems.Add(miFile)
' Set the form's menu to the menu you have just created.
Me.Menu = mmAppStart
End Sub
// C#
// Create a MainMenu object and a MenuItem object.
MainMenu mmAppStart;
MenuItem miFile;
public void AppStartMenu(){
// Create an instance of the MainMenu object.
mmAppStart = new MainMenu();
// Create a top-level menu item and two menu items. Use this
// overloaded constructor that takes an event handler
// (MenuSelect) so that later, you can cause the menu selection
// to change the application state.
miFile = new MenuItem("&File", new EventHandler(MenuSelect));
miFile.MenuItems.Add("&New", new EventHandler(MenuSelect));
miFile.MenuItems.Add("&Open", new EventHandler(MenuSelect));
miFile.MenuItems.Add("&Exit");
// Add the top-level menu item to the MainMenu component
// and set the MainMenu component to be the form's menu.
mmAppStart.MenuItems.Add(miFile);
// Set the form's menu to the menu you have just created.
this.Menu = mmAppStart;
}
// C++
// Create a MainMenu object and a MenuItem object.
private: System::Windows::Forms::MainMenu * mmAppStart;
private: System::Windows::Forms::MenuItem * miFile;
private:
void AppStartMenu()
{
// Create an instance of the MainMenu object.
mmAppStart = new System::Windows::Forms::MainMenu();
// Create a top-level menu item and two menu items. Use this
// overloaded constructor that takes an event handler
// (MenuSelect) so that later, you can cause the menu selection
// to change the application state.
miFile = new MenuItem(S"&File",
new EventHandler(this, MenuSelect));
miFile->MenuItems->Add(S"&New",
new EventHandler(this, MenuSelect));
miFile->MenuItems->Add(S"&Open",
new EventHandler(this, MenuSelect));
miFile->MenuItems->Add(S"&Exit",
new EventHandler(this, MenuSelect));
// Add the top-level menu item to the MainMenu component
// and set the MainMenu component to be the form's menu.
mmAppStart->MenuItems->Add(miFile);
// Set the form's menu to the menu you have just created.
this->Menu = mmAppStart;
}