Menu items are more complicated, because they can be rendered
recursively. Take the File menu in some applications, like Visual Studio. The
file menu can have New and Recent menu items as children, which New can have
its own children (the type of file to create), which theoretically could have
their own children, and so a recursive amount of relationships can exist.
To facilitate that, each menu item has an Items collection,
which it listens for child items being created, so it can bubble up a child
item event. For instance, below is the collection of items within the MenuItem
object:
Listing 8
public MenuItemCollection Items
{
get
{
if (_items == null)
{
_items = new MenuItemCollection();
_items.ItemAdded += ChildItems_ItemAdded;
_items.ItemAdding += ChildItems_ItemAdding;
_items.ItemInserted += ChildItems_ItemInserted;
_items.ItemInserting += ChildItems_ItemInserting;
_items.ItemRemoved += ChildItems_ItemRemoved;
_items.ItemRemoving += ChildItems_ItemRemoving;
}
return _items;
}
}
This class listens for each event, and uses the
On<EventName> method to bubble up the event.
Listing 9
void ChildItems_ItemAdded(object sender, DataEventArgs < MenuItem > e)
{
this.OnChildItemAdded(e);
}
protected virtual void OnChildItemAdded(DataEventArgs < MenuItem > e)
{
if (ChildItemAdded != null)
ChildItemAdded(this, e);
}
The ChildItemAdded event is listened to by the parent, which
will be discussed later. The menu item adds one more item of importance, which
is the Path property. Because menu item is a hierarchy element, this property
returns the name of each item in an object that is a string collection of the
names. Below is the implementation of this property, and the important
methods.
Listing 10
public ValuePath Path
{
get
{
ValuePath path = new ValuePath();
path.AddValues(this.GetParentNames(this));
return path;
}
}
private string[]GetParentNames(MenuItem item)
{
List < string > names = new List < string > ();
if (item.Parent != null)
{
names.AddRange(this.GetParentNames(item.Parent));
names.Add(item.Name);
return names.ToArray();
}
else
return new string[]
{
item.Name
};
}
You can see that recursion comes into play with the
GetParentNames method. It has to return a single element as a string, so I can
leverage using the same method in a recursive manner.