private bool UpdateAlbumName string newName, object obj { ListViewItem item = obj as ListViewItem; TreeNode node = obj as TreeNode; // Determine the file name string fileName = null;
Trang 1As we mentioned at the start of this section, we will not spend much time discussingthese changes, since they leverage concepts and features we have seen before Let’smove on to editing a tree node’s label.
15.5.2 SUPPORTING LABEL EDITS
Tree nodes can be edited in a manner similar to list items There is a BeginEdit
method in the TreeNode class to initiate a label edit programmatically, and eLabelEdit and AfterLabelEdit events in the TreeView class that occur beforeand after the user edits the label Event handlers for these events receive the NodeLa- belEditEventArgs class for the event parameter This class is summarized in.NET Table 15.5, and is manipulated in much the same way as we saw for the
Befor-LabelEditEventArgs class when handling label events for the ListView class
5 Update the AfterSelect event
handler to use the new
DisplayPhoto method to ensure the proper control is visible.
private void treeViewMain_AfterSelect( .) {
.
if (node.Parent == null) {
// Bad tag or top-level node.
LoadAlbumData(fileName);
DisplayPhoto(null);
} else if (Path.GetExtension(fileName) ) {
// Album node selected PhotoAlbum album = OpenTreeAlbum( .); LoadPhotoData(album);
DisplayPhoto(null);
} else // must be a photograph {
// Clear the list and display the photo listViewMain.Clear();
DisplayPhoto(node);
} }
6 Add a Resize event handler for
the PictureBox control to force the control to redraw the entire image when it is resized.
private void pictureBoxMain_Resize (object sender, System.EventArgs e) {
// Force the entire control to repaint pictureBoxMain.Invalidate();
}
Trang 2F UN WITH TREE VIEWS 517
In our application, we will permit nodes to be edited using the menuEditLabel
menu item, or by pressing the F2 key when a tree node is selected and the tree viewhas the focus The following table details the steps required for this change:
.NET Table 15.5 NodeLabelEditEventArgs class
The NodeLabelEditEventArgs class represents the event data associated with the eLabelEdit and AfterLabelEdit events in the TreeView class This class is part of the
Befor-System.Windows.Forms namespace, and inherits from the System.EventArgs class.
Public Properties
CancelEdit Gets or sets whether the edit operation should
be cancelled This property can be set both before and after the node is edited.
Label Gets the new text to assign to the label of the
indicated node.
Node Gets the TreeNode object being edited.
S UPPORT EDITING OF TREE NODE LABELS
1 Set the LabelEdit property for
the TreeView control to true
in the MainForm.cs [Design]
window.
Tree node labels may now be edited.
2 Handle the KeyDown event for
the TreeView control to initiate
a label edit when the F2 key is pressed in the tree control.
private void treeViewMain_KeyDown (object sender, System.Windows.
Forms.KeyEventArgs e) {
if (e.KeyCode == Keys.F2) {
if (treeViewMain.SelectedNode != null) {
treeViewMain.SelectedNode.BeginEdit(); e.Handled = true;
} } }
3 Update the menuEdit_Popup
event handler to use the text
“Node” for the
menuEditLabel menu when the TreeView has the focus.
if (treeViewMain.Focused)
{ menuEditLabel.Enabled = (treeViewMain.SelectedNode != null); menuEditLabel.Text = "&Node";
} else // assume ListView has focus {
menuEditLabel.Enabled = (listViewMain.SelectedItems.Count > 0);
if (this._albumsShown) menuEditLabel.Text = "&Name";
else menuEditLabel.Text = "&Caption";
}
}
Trang 34 Update the
menuEdit-Label_Click event handler to edit the appropriate item based
on the current focus.
private void menuEditLabel_Click (object sender, System.EventArgs e) {
if (treeViewMain.Focused)
{
if (treeViewMain.SelectedNode != null) treeViewMain.SelectedNode.BeginEdit(); }
else if (listViewMain.SelectedItems.Count > 0)
listViewMain.SelectedItems[0].BeginEdit(); }
5 Handle the AfterLabelEdit
event for the TreeView control.
Note: We permit the user to
edit the root node here to alter
a top-level name in the tree, even though this change is dis- carded when the application exits A more robust solution might be to prevent this from occurring, or to save the change in a configuration file.
private void treeViewMain_AfterLabelEdit (object sender, System.Windows.
Forms.NodeLabelEditEventArgs e) {
if (e.Label == null) {
// Edit cancelled by the user e.CancelEdit = true;
return;
}
// No changes required for root node
if (e.Node.Parent == null) return;
string fileName = e.Node.Tag as string;
if (Path.GetExtension(fileName) == ".abm") e.CancelEdit = !UpdateAlbumName(e.Label, e.Node); else
e.CancelEdit = !UpdatePhotoCaption(e.Label, e.Node); }
6 Rewrite the
UpdateAlbum-Name method to accommodate both list items and tree nodes.
private bool UpdateAlbumName
(string newName, object obj)
{ ListViewItem item = obj as ListViewItem; TreeNode node = obj as TreeNode;
// Determine the file name string fileName = null;
if (item != null) {
fileName = item.Tag as string;
node = FindNode(fileName, false);
} else if (node != null) fileName = node.Tag as string;
Note: Recall that the list view’s AfterLabelEdit
event handler from chapter 14 provides a Item object when calling this method This invocation
ListView-is still valid and ListView-is properly dealt with by thListView-is code.
c Determine the file name for the appropriate object.
d If the object is a list view item, also find the node cor- responding to this item.
Trang 4F UN WITH TREE VIEWS 519
7 Rename the file.
newFileName = RenameFile(fileName, newName, ".abm"); }
if (newFileName == null) {
MessageBox.Show("Unable to rename album " + "to this name.");
return false;
}
8 Update the Tag property for the
appropriate object.
Note: When the object is a list
item, this updates the sponding node as well.
// Update the appropriate Tag property
if (item != null) {
item.Tag = newFileName;
if (node != null) node.Text = newName;
} else if (node != null) node.Tag = newFileName;
return true;
}
9 Rewrite the
UpdatePhoto-Caption method to modate both list items and tree nodes.
private bool UpdatePhotoCaption
(string caption, object obj)
{ ListViewItem item = obj as ListViewItem; TreeNode node = obj as TreeNode;
// Determine the album index int index = -1;
if ((item != null) && (item.Tag is int)) {
index = (int)item.Tag;
node = FindNode(_album[index].FileName, false);
} else if (node != null) {
param-b Convert the given object
to both a list item and a tree node.
c Determine the album index for the appropriate object.
d If the object is a list view item, also find the node corresponding to this item.
Trang 5Our program now permits editing of nodes in the TreeView and items in the View Editing is initiated with the menuLabelEdit menu or the F2 key, and isbased on which control currently has the focus.
List-In both update methods, note how the as keyword is used to convert the givenobject into both a TreeView and a ListView, as is shown in the following excerpt.The remainder of each method executes the appropriate statements based on whichtype of control is provided
ListViewItem item = obj as ListViewItem;
TreeNode node = obj as TreeNode;
Also of note is our use of the FindNode method created earlier in the chapter as part
of section 15.4.2 As you may recall, we included a parameter to this method thatindicated whether to expand the selected node We set this second parameter to
false here to ensure that the contents of the tree view control are not altered.Our final change is to support the display of our album and photograph propertydialogs from the TreeView control
In chapter 14 we created a Properties menu We handled the Click event for thismenu in a menuProperties_Click method, and created the DisplayAlbumProp- erties and DisplayPhotoProperties methods to display the two types of dialogsrequired Here we would like to change the behavior of this menu to the following:
•When the TreeView has the focus, display the appropriate properties dialog if
an album node or a photograph node is selected
•When the ListView has the focus, display the appropriate properties dialogfor the selected item
•When the PictureBox has the focus, display the photograph properties log associated with the displayed image
dia-To make this change, we will modify our Display methods to accept either a ViewItem or a TreeNode object The following table details the changes required
List-11 Update the photograph’s
caption, and save the changes
to the album.
Note: When the object is a list
item, this updates the sponding node as well.
// Update caption _album[index].Caption = caption;
if (item != null && node != null) {
// Update node text as well node.Text = caption;
Trang 6F UN WITH TREE VIEWS 521
U PDATE P ROPERTIES MENU TO HANDLE TREE NODES
1 In the MainForm.cs code
window, update the
menuProperties_Click event handler to accommodate the three controls that might have the focus.
private void menuProperties_Click (object sender, System.EventArgs e) {
if (treeViewMain.Focused) {
TreeNode node = treeViewMain.SelectedNode; string file = node.Tag as string;
if (node == null || node.Parent == null || file == null)
return; // do nothing
if (Path.GetExtension(file) == ".abm") DisplayAlbumProperties(node);
else DisplayPhotoProperties(node);
} else if (pictureBoxMain.Focused) {
// Display photograph for this image TreeNode node = treeViewMain.SelectedNode;
if (node != null) DisplayPhotoProperties(node);
} else
if (listViewMain.SelectedItems.Count > 0) {
ListViewItem item = listViewMain.SelectedItems[0];
if (this._albumsShown) DisplayAlbumProperties(item);
else DisplayPhotoProperties(item);
} }
2 Rewrite the
DisplayAlbum-Properties method to accept
an object instance.
private void DisplayAlbumProperties
(object obj)
{ ListViewItem item = obj as ListViewItem; TreeNode node = obj as TreeNode;
// Open the album as appropriate PhotoAlbum album = null;
if (item != null) {
string fileName = item.Tag as string;
if (fileName != null) album = this.OpenAlbum(fileName); }
else if (node != null) {
album = OpenTreeAlbum(node);
}
if (album == null) // as in chapter 14
How-to
a For the TreeView control, ignore the parent node and call the appropriate Proper- ties method based on the node type.
b For the PictureBox control, call the DisplayPhoto- Properties method on the selected photo node.
c For the ListView control, the code is the same as in chapter 14.
Trang 73 When displaying the album edit
dialog, only update the list item settings if the given item is a list view item.
Note: If the given item is a tree
node, then photographs are played in the list view, and these settings should not be updated.
using (AlbumEditDlg dlg = new AlbumEditDlg(album)) {
if (dlg.ShowDialog() == DialogResult.OK) {
// Save changes made by the user
// Update item settings
if (item != null) {
item.SubItems[MainForm.
AlbumTitleColumn].Text = album.Title;
bool hasPwd = (album.Password != null) && (album.Password.Length > 0); item.SubItems[MainForm.
AlbumPwdColumn].Text = (hasPwd ? "y" : "n");
} } }
Trang 8F UN WITH TREE VIEWS 523
As you can see, the display methods use the as keyword to convert a given object
into both a ListViewItem and a TreeNode instance Whichever instance is
non-null indicates how to display the property dialog
TRY IT! As a further change to our TreeView control, add a context menu to this
control to perform the following tasks
1 An “Add Directory” menu item that permits a new album directory to
be added to the tree This should prompt for a directory name and add
a top-level node to the tree for each album discovered in that directory
2 A “Properties” menu item that displays the properties dialog for thenearest node This should select the nearby node, and then call the
PerformClick method for the menuProperties menu
3 A “Delete” menu item that deletes a node from the tree This shoulddelete the album file from the file system or the Photograph from thecontaining album for the given node You should prompt the user tomake sure they really wish to do this
You will need to use the GetNodeAtmethod to locate the TreeNodeinstance at agiven pixel position, so that the action applies to the specific tree node located at thecurrent mouse position
5 After displaying the dialog,
update the list or node with any modified photograph settings.
Note: Recall that our photo edit
dialog permits all photographs
in an album to be updated As a result, when the photographs are shown in the tree node, the label for each related node must
be updated as well This is true regardless of the type object
given.
using (PhotoEditDlg dlg = new PhotoEditDlg(_album)) {
if (dlg.ShowDialog() == DialogResult.OK) {
// Save any changes made
// Update controls with new settings TreeNode baseNode = null;
if (item != null) {
LoadPhotoData(_album);
baseNode = treeViewMain.SelectedNode; }
else if (node != null) {
baseNode = node.Parent;
}
if (baseNode != null) {
// Update all child labels foreach (TreeNode n in baseNode.Nodes) {
n.Text = _album[n.Index].Caption; }
} } } }
U PDATE P ROPERTIES MENU TO HANDLE TREE NODES (continued)
Trang 9You could also implement these items within the ListViewcontrol as well.This completes our discussion on the TreeViewclass Before we move on, let’s do aquick recap of what we covered in this chapter.
15.6 R ECAP
In this chapter we extended the MyAlbumExplorer project built in chapter 14 to add
a TreeView control We divided our main window using the Splitter class inorder to create a classic explorer window such as that used in the Windows operatingsystem for browsing the file system
A tree view contains a hierarchy of TreeNodeobjects, and we created a tree playing our album files and the photos in each album We discussed common oper-ations within a tree view such as expand, collapse, selection, and label editing Duringthe course of the chapter, the ListViewand TreeViewcontrols were integrated todisplay a common interface, with changes to one control reflected in the other control
dis-We also added a PictureBoxcontrol in order to display the image associated with
a selected photograph node in the tree
The explorer interface we saw in these last two chapters is one of three kinds ofstandard Windows interfaces In part 2 of this book we built what is called a singledocument interface In the next chapter we will look at another kind of interface,namely the multiple document interface
Trang 10The ListView and TreeView classes discussed in chapters 14 and 15 present a lection of objects within a single list or tree control These are especially useful whencreating an explorer-style interface such as our MyAlbumExplorer application, or thecommon Windows Explorer application Another kind of interface is the multiple
col-document interface, also called an MDI (normally pronounced em-dee-eye).
An MDI application presents a collection of forms within a single applicationwindow We will discuss MDI applications through the following discussion areas:
•Understanding various interface styles
•Creating an MDI container window
•Converting an SDI application into an MDI application
•Using MDI-related class members of various controls
•Merging two menus into a single merged menu
•Managing menus and forms in an MDI application
These topics will be covered as we progress through the chapter, beginning with theconcept of interface styles
Trang 1116.1 I NTERFACE STYLES
Before we discuss exactly how multiple document interfaces are created, let’s take astep back and consider the various types of application interfaces used for Windowsapplications Most Windows applications fall into one of three interface categories:
•Single document interfaces
•Explorer interfaces
•Multiple document interfaces
We will discuss each type of interface separately
A single document interface, also called an SDI, is an interface that displays a singledocument or other encapsulated data within a single form Our MyPhotos applica-tion, as shown in figure 16.1, is a good example of this style, in which a single photoalbum is displayed The user can look at multiple photo albums only by examiningone after another The contents of two albums cannot be compared unless two copies
of the program are running
In the Windows operation system, the Notepad and WordPad applications vide additional examples of the SDI style
pro-16.1.2 EXPLORER INTERFACES
The MyAlbumExplorer application built in chapters 14 and 15 is an example of anexplorer interface, and can be seen in figure 16.2 In this style, a hierarchy of informa-tion is presented to the user Normally a TreeView control displays this hierarchy,typically on the left, with details on the selected node provided in a ListView con-trol Sometimes the TreeView control can be hidden, and sometimes it is always
Figure 16.1 Our single document interface displays one photo album at a time.
Trang 12I NTERFACE STYLES 527
present Alternate information may appear on the list side of the window as well, such
as the photographic image we displayed in chapter 15 for a selected photograph inthe MyAlbumExplorer application
In Windows, of course, the Windows Explorer application is another example ofthis style
A multiple document interface (MDI) allows multiple views of one or more ments or other encapsulated data to be displayed at the same type This permits alter-nate views of the same data, or separate presentations of the same style of data, within
docu-a single window For exdocu-ample, docu-a stock mdocu-arket MDI docu-applicdocu-ation might present ent historical or graphical views of a single portfolio, each as a separate window Alter-nately, such an application might present multiple portfolios, each as its own windowwithin a containing application window
differ-In the original conception of this style, a single window acted as a container forother windows, where each contained window displayed a specific instance or view of
a type of data More recently, well-known MDI applications such as Microsoft Wordand Excel have taken the approach of displaying all of their windows directly on thedesktop, each within a separate application window, while still preserving an MDIlook and feel from the menu bar and other parts of the interface This relatively newstyle, the Multiple Single Document Interface, or MSDI, is consistent with the man-ner in which Web browsers have typically worked While an MSDI interface can becreated in Visual Studio.NET, it is not necessarily an easy task
Figure 16.2 Our explorer interface presents the collection of photo albums in list form.
Trang 13Also note that Visual Studio NET, while providing an MDI-like interface, usesmore of a TabControl look and feel for the set of displayed windows, or what might
be called a Multiple Tabbed Documents Interface, or MTDI In this style, multiplesets of windows are displayed as horizontal or vertical groups of tabs Both the MSDIand MTDI approaches can be created using the NET Framework as an alternative tothe traditional MDI interface, although there is not really any direct support for thesenewer interfaces As a result, implementing such interfaces requires much more effortfrom the developer
For our purposes, a traditional MDI application provides the means to discussand demonstrate the manner in which the NET Framework supports such applica-tions We will convert the existing MyPhotos application into the MDI applicationshown in figure 16.3 As you can see, this application will incorporate the Form classes
we have created in part 2 of this book
The reuse of our existing classes is possible because of the manner in which the Form
class in general and MDI support in particular is integrated into the Windows Formshierarchy As we discussed in chapter 7, a Form object is a Control instance thathappens to display an application window For MDI applications, Form controls arecontained by a parent Form Of course, the contained forms can be resized andmoved within their container, and can still display menus, toolbars, status bars, andother controls As we shall see, the relationship between MDI parent and child forms
is different than the relationship between control containers and controls
Figure 16.3 Our multiple document interface, created in this chapter, displays a
se-lected set of photo albums within a single window.
Trang 14I NTERFACE STYLES 529
To provide some insight and perhaps some perspective on MDI applications, the lowing table lists a number of class members specific to the implementation of MDIapplications in the NET Framework Of course, these members can be used forother purposes, and additional properties, methods, and events are certainly used inMDI applications These events highlight many of the MDI-specific tasks that areoften performed in this style interface The table provides a short description of eachmember and a reference to the section in this chapter where more information oneach item may be found
fol-Class members often used in MDI applications
Class Member
type Member name Description
See section
MdiChildren Gets the set of MDI children contained by
this form as an array of Form objects.
16.4.3
MdiParent Gets or sets the MDI container for this form
If set, then this form is an MDI child form.
16.2.2
MergedMenu Gets the MainMenu object representing the
current merged menu for an MDI container form.
16.3
Methods LayoutMdi Arranges the MDI children within this form
using a given layout style.
16.5.1
Events MdiChildActivate Occurs when an MDI child form is activated
or deactivated within an MDI application
Note that MDI children do not receive the
Activated and Deactivate events.
16.4.4
Menu
Properties MdiListItem Gets the MenuItem object contained by this
menu that displays a list of MDI child forms for the associated form object.
16.5.2
Methods MergeMenu Merges the MenuItem objects in a given
menu with those contained by this menu.
16.3
MenuItem
Properties MdiList Gets or sets whether this menu should be
populated with a list of MDI child forms contained by the associated form.
16.5.2
MergeOrder Gets or sets the relative position of this menu
item when it is merged with another menu.
16.3.2
MergeType Gets or sets how this menu should be
merged with other menus The default is
MergeType.Add
16.3.1
Trang 15Also note that the behaviors of desktop-related actions within an MDI child form aremodified For example, the Minimize and Maximize buttons on the title bar workwithin the parent window, rather than on the desktop itself.
In the rest of this chapter we will enhance our MyPhotos application to support
a multiple document interface We begin with the MDI container form
16.2 MDI FORMS
So let’s convert our existing MyPhotos application into an MDI application This tial work is not as difficult as you might think Generally, we need one Form to act asthe top-level container, and the ability to create other forms as children within thiscontainer Here, we will do this via the following tasks:
ini-1 Create a new parent form for the application to act as the MDI container
2 Add a menu bar and New menu item to create MDI child forms
3 Define a new Main method in the parent as the entry point for the application
Of course, there will be other work to perform to clean up the behavior of our cation These steps will get us going, and subsequent sections will deal with otherrequired changes Figure 16.4 shows how our application will look by the end of thissection Note in particular the two File menus We will address this issue in the nextsection while discussing Merged Menus
appli-Figure 16.4 Note the two File menus for this window The menus from both
our ParentForm and MainForm classes appear separately on the menu bar We
will address this in section 16.3.
Trang 16MDI FORMS 531
The creation of an MDI container form is much like the creation of any other form.Such a form is often referred to as a parent form, since it acts as the parent for one ormore MDI child forms The following table details the steps required for this task
Set the version number of the MyPhotos application to 16.2.
As you can see, the contents of the window appear in a darker color and includes a
3-D border to indicate that this form is now an M3-DI container This color is the tem.AppWorkspacecolor, which is typically a darker version of the System.Con- trol color This background is a hidden MdiClient control, and cannot bemanipulated in code as it is not exposed by the Form class This background containsthe MDI child forms, and is always last in the z-order As a result, any controls added
Sys-to the form will appear above this background, and therefore in front of any MDIchildren Typically, controls added to an MDI container are docked to one edge ofthe parent form
The code generated for our ParentForm class is much like other forms we haveseen in this book The InitializeComponent method generated by Visual Studio.NET is as follows:
private void InitializeComponent()
{
//
// ParentForm
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(592, 373);
C REATE A NEW FORM AS AN MDI CONTAINER
1 In the Solution Explorer window,
add a new Windows Form to the application called ParentForm
The new file appears in the Solution Explorer window and the ParentForm.cs [Design] window is displayed.
2 Set the icon property for the
form to the “icons/Writing/
BOOKS04.ICO” file in the common image directory.
3 Set the IsMdiContainer
property to true
Note: This establishes the form
as an MDI container form.
4 Set the Size property to
600×400 pixels.
Trang 17this.Name = “ParentForm”;
this.Text = “ParentForm”;
}
With the parent form created, we can turn our attention to the child form
With our MDI container in place, we can add the infrastructure required for ing MDI child forms This will consist of a menu bar and a New menu item Fortu-nately, we already have our MainForm class available to act as the child form.The following table shows how to create a child form in our application As part
generat-of this task, we will add an Exit menu as well
A DD ABILITY TO CREATE CHILD FORMS
1 Add a MainMenu object to the ParentForm
class in the ParentForm.cs [Design] window.
2 Add a top-level File menu containing the
three menu items as shown.
3 Add a Click event handler for the Exit
menu to close the form.
private void menuExit_Click (object sender, System.EventArgs e) {
Settings Menu Property Value
File (Name) menuFile
Text &File New (Name) menuNew
Shortcut CtrlN Text &New
separator
Exit (Name) menuExit
Text E&xit
Trang 18One quite simple means to fix our entry point would be to modify the Main method
in the MainForm class directly The new code would look as follows, with the changehighlighted in bold:
public class MainForm : System.Windows.Forms.Form
ParentForm class, and modify the project to use this new method as the entry point.The following table creates a new entry point within the ParentForm class
5 Within this handler, create a MainForm
object as an MDI child form.
MainForm newChild = new MainForm(); newChild.MdiParent = this;
a Create a new MainForm object.
b Define this form as an MDI child by ting the current form as its MDI parent.
set-c Display the child form using the Show
method.
Trang 19The application is now ready The startup object specified here is used by the C#compiler to establish the entry point for the application, and is only required if thereare multiple Main methods in your project On the command-line, the C# compileraccepts the /main switch to specify the class containing the Main method to use asthe application’s entry point.
Run the application to verify that the ParentForm window appears and the Newmenu can be used to create MainForm objects as child windows If you explore this newapplication, you will find some rather peculiar behavior for some of the controls Wewill discuss and address these issues throughout the remainder of this chapter
TRY IT! Of course, the MyPhotos Property Pages dialog used in step 2 can also be
used to set the Startup Object to the MyPhotos.MainForm class Whenthis is done, the application displays the familiar single document interfacecreated in part 2 of this book Make this change and run the application toobserve this behavior
Among the odd features you may notice in the MDI version of this application is themenu bar In particular, there are two File menus when a MainForm window is dis-played Adjusting this behavior is our next topic
C REATE AN ENTRY POINT IN THE PARENT FORM
1 Create a Main method in the
ParentForm.cs code window to serve as the entry point for our MDI application.
Note: If you compile the
applica-tion after this step, you will get an error indicating that the program defines more than one entry point.
2 Set the Startup Object for the
MyPhotos project to the
associ-c Select the Form class.
Trang 20MyPhotos.Parent-M ERGED MENUS 535
16.3 M ERGED MENUS
By definition, an MDI application permits multiple windows to be displayed Eachchild window may be the same or different, and each may display different informa-tion about one or more objects It would be nice if the menu items for the applicationcould be customized depending on which child window is displayed Exactly how to
do this is the subject of this section
As an example, consider a car-buying application that permits users to search for,display, and purchase used cars As an MDI application, this might display a photo-graph of the car in one window, standard features and warranty information inanother window, and optional packages and pricing information in a third window.Clearly the set of menus and the contents of each menu should differ depending onwhich style window is currently active For instance, menus for the photograph win-dow might permit different colors to be viewed or different parts of the vehicle to beshown These concepts make no sense for the other windows, and should not be acces-sible when these windows are active
While our application is not quite so ambitious, we do have the problem of ourFile menu, since both the ParentForm and the MainForm class contain this item.Once we make the two File menus merge, we also have to deal with the contents ofthese menus, to ensure the items appear in an appropriate order
The Menu class provides a MergeMenumethod for merging two menus together.This method accepts a Menu object and merges it with the calling Menuobject The
MenuItem class provides additional overrides of this method to merge MenuItem
objects and to copy a menu item so that it may be merged with other menus This ter method has the advantage of not affecting the existing MenuItemobject
lat-In MDI applications, an MDI container form automatically merges the menu forthe active child form with the MainMenuobject stored in its Menu property The
Form.MergedMenuproperty contains the result of this merge, and can be used toaccess or modify the merged menu directly The Form.Menuproperty always containsthe original menu assigned to the form
Since this merging occurs automatically for MDI applications, this section willfocus on how menus are merged together, and make the appropriate changes in ourMDI application to merge the two File menus together First we will discuss the var-ious ways to merge two menus, followed by the mechanism for establishing the order
of merged menu items
As mentioned at the start of this chapter, the MenuItem class contains two propertiesthat control exactly how two menus are merged together This section will discuss the
MergeType property that controls how the menus are merged Later we will look atthe MergeOrder property that controls the final position of a merged item
Trang 21The MergeTypeproperty gets or sets a MenuMergeenumeration value ing how this menu should be merged with other menus An overview of this enumer-ation appears in NET Table 16.1 The default setting for the MergeTypeproperty
specify-is MenuMerge.Add This default adds each item separately, and is the cause of the twoFile menus in our current application
This explains why our existing application has two File menus Since the MergeType
property defaults to Add, the menus are simply added to the collection separately
We can fix this by modifying the MergeType property for these menus
Set the version number of the MyPhotos application to 16.3.
Compile and run the application, and open a client form in the parent window to seethe merged menu as shown in the table The two menus are merged, but their contents
.NET Table 16.1 MenuMerge enumeration
The MenuMerge enumeration specifies various types of behavior for a MenuItem object when it is merged with another menu This enumeration is used by the MergeType property
in the MenuItem class, and is part of the System.Windows.Forms namespace.
Enumeration Values
Add The item is added to the collection of MenuItem
objects in the merged menu.
MergeItems All MenuItem objects contained by the item are
merged with those contained by the menu at the same position in the merged menu.
Remove The item is not included in the merged menu Replace The item replaces an existing MenuItem object
at the same position in the merged menu.
M ERGE THE PARENT AND CHILD F ILE MENUS
1 In the MainForm.cs [Design]
window, set the MergeType
property of the File menu item
to MergeItems
The two File menus in the parent and child form will now merge into a single menu in the application, the result of which is shown in this graphic The menu items exhibit the default merge behavior, which is Add
2 Similarly, set the MergeType
property to MergeItems for the File menu in the ParentForm.cs [Design] window.
Note: The MergeType property must be set for both File menu objects to merge the two menus together.
Trang 22We can fix this, of course, but first a brief aside.
TRY IT! Modify the MergeType property for either File menu so that one menu
uses the MergeItems member value and the other the Add value Run theapplication to verify that the menus no longer merge
Also rename the File menu in the ParentForm class to use the name
“Fickle.” Run the application and see which name is shown in the tion You will find that the name in the MDI child is preferred over thename in the parent This is a consequence of how the menus are merged,and can be utilized to rename a menu in the parent form when a specifickind of child is displayed
applica-Back in our application, we have two problems with the merged File menu The first
is that we have two versions of the New and Exit menus, and the second is that theorder of the merged menu is a bit of a mess
We will address these two problems together as part of a discussion on the Orderproperty
So far we have merged our two File menus into a single menu The next step is toclean up the contents of this menu This involves setting the appropriate MergeType
for each menu, and using the MergeOrder property to establish the order of theseitems within the merged menu The MergeOrder property contains the zero-basedposition where the menu should appear within the merged menu If multiple itemsare assigned the same order, they appear one after another in the merged menu This
is the case in our existing code, where all menus in the File menu use the default
MergeOrder value of zero
Before we start making changes to our existing menus, let’s step back and considerwhat a reasonable File menu should contain for our MDI application Such a menu
is described by the following table, which shows the menu name, its position, a shortdescription, and some implementation notes
Contents of the merged File menu in our MDI application
Menu name Position Description Implementation Notes
New 0 Opens a new album in a new MDI
child window.
Same as existing New menu in the
ParentForm class.
Open 1 Opens an existing album file in a
new MDI child window.
This should be processed by the
ParentForm class in order to create the new child window.
Trang 23This details how the merged menu should look There is still the question of themenu structure in the ParentForm and MainForm classes Based on the previoustable, we can establish how the File menu should appear for each Form class The fol-lowing table details the contents of each menu, and describes its behavior in themerged menu object.
We are now ready to update our menus based on these tables Our first change willsimply update the menus so that they appear as described within the application
Close 2 Closes the active MDI child
child window under a new name.
Same as existing Save As menu in the MainForm class.
separator 6
Exit 7 Closes all child windows as well as
the MDI container form.
Same as existing Exit menu in the
ParentForm class.
Individual File menu for our MDI parent and child classes
Class Menu Implementation notes
ParentForm
New This menu should behave as it already does, and replace the New menu
in the child form.
Open This is a new menu to open an existing album in a new window.
separator This menu should not exist when the menus are merged.
Exit This menu should behave as it already does, and appear at position 7
when the menus are merged.
Save As As currently exists, at position 5 in the merged menu.
separator Should become the second separator at position 6 in the merged menu Exit Should become the Close menu at position 2 in the merged menu.
Contents of the merged File menu in our MDI application (continued)
Menu name Position Description Implementation Notes
Trang 24M ERGED MENUS 539
Once this is done, we will look at implementing any changes required to supportthese menus
The following table details the steps required:
The key points here are the fact that the New and Open menus in the ParentForm
class replace those in the MainForm class, and the merge order for each menu mustmatch the desired position we discussed earlier One other interesting point is thereuse of the Exit menu in the MainFormclass for the Close menu in the mergedmenu This makes sense, although we still need to rename the menu text to read
A SSIGN THE TYPE AND ORDER FOR OUR F ILE MENUS
1 In the ParentForm.cs [Design]
window, add an Open menu to the File menu just after the existing New menu.
2 Update the merge settings for the
items in the File menu.
3 In the File menu for the MainForm.cs
[Design] window, update the merge settings for the items in this menu.
Settings Property Value
(Name) menuOpen Shortcut CtrlO Text &Open
Settings Menu MergeType MergeOrder
New Replace 0 Open Replace 1
separator Remove 0 Exit Add 7
Settings
Menu MergeType MergeOrder
New Remove 0 Open Remove 1 separator Add 3 Save Add 4 Save As Add 5 separator Add 6 Exit Add 2
Trang 25“Close” rather than “Exit.” We will do this in a way that continues to preserve theSDI application from part 2.
This change ensures that the Exit menu displays “Close” when the MainForm object iscreated as an MDI child window Otherwise, the default setting of “Exit” will be used.Compile and run the application to verify that our changes produce the appro-priate menu structure Create a new MDI child window and display the File menu.Your application should appear as in figure 16.5 Note how all the menus are now inthe desired order, including the separator menus Also note that the Exit menu fromthe MainForm class is reincarnated as the Close menu in the MDI application
C HANGE THE E XIT MENU TEXT WHEN RUNNING AS AN MDI CHILD FORM
4 Override the OnLoad method in
the MainForm.cs code window.
protected override void OnLoad(EventArgs e) {
5 If the form is an MDI child
window, then modify the Exit menu to appear as a Close menu.
How-to
Use the IsMdiChild property.
if (IsMdiChild) menuExit.Text = "&Close";
base.OnLoad(e);
}
Figure 16.5 The merged File menu here gives no indication that different
menu items are processed in different classes.