For the Menu, I abstracted away the typical BeginComposite...EndComposite, hiding these inside a custom
. This helps make the code even more concise.
Notice that for simplicity, regular Menus are used for the sub-menus as well. These sub-menus are displayed OnClick of a MenuItem. The sub-menus are wrapped in a Border parent and added as children to a Canvas parent (which is a child of MainWindow.) Canvas allows support of Z-Index.
WPF Composites is all about Parent-Child relationships and nested parent-children.
This approach may be reminiscent of old-school DHTML menus on the web which would hide or show DIV tags on click or mouseover of a menu-item. In WPF, perhaps the Border may be the new DIV tag?
In the demo app, in MenuBuilder.cs, I include at the bottom a commented-out section of code that shows an example of using the regular
theme color & styling with regular sub-menus (IsSubmenuOpen). However, my assumption is that most developers prefer to style the menu to suit their own taste with their own custom colors, etc. as shown in the code example below and the screenshot above which leverage the more DHTML-like approach:
//TOP-LEVEL MENU BAR
mnu = FasterWPF.Factory
.BeginMenuSettings(double.NaN, 20D, ContainerType.HorizontalPanel, Brushes.WhiteSmoke)
.SetItemBorderSettings<Menu>(110D, 20D, Brushes.Silver, new Thickness(2))
.EndMenuSettings();
. . . . . . . .
public static class MenuBuilder
{
public static void BuildMenu(Menu mnu, Canvas cnvs, string cnvsguid2, string cnvsguid3, string submnuguid0, string submnuguid1)
{
//MENU ITEM 1
MenuItem m1 = FasterWPF.Factory
.BeginMenuComposite("_File", mnu, Brushes.WhiteSmoke, Brushes.WhiteSmoke, Brushes.Black, Brushes.Black, "Verdana", 12, FontWeights.Bold, FontStyles.Normal, Brushes.WhiteSmoke)
.SetMouseOverBorderColor(Brushes.Gray)
.AddMenuItem((o, ev) => { MessageBox.Show("Clicked File!"); })
.EndMenuComposite();
//SUB-MENU 1
//Step 1: create a Border to hold the sub-menu and set it to hide itself on mouse-out
Border subMenuBorder = new Border();
subMenuBorder.Initialize(230D, 100D, ContainerType.HorizontalPanel, Brushes.Gray, new Thickness(1), Brushes.WhiteSmoke);
subMenuBorder.BeginSettings<Border>().SetItemBorderSettings<Border>(230D, 100D, Brushes.LightGray, new Thickness(1)).EndSettings<Border>();
subMenuBorder.SubscribeEventOnParent<Border>("MouseLeave",
new MouseEventHandler((o, mse) =>
{
//a: On mouse out, hide sub-menu
MenuItemExt.HideSubMenu(cnvs, cnvsguid2);
}));
//Step 2: create the submenu and set its orientation to vertical
Menu subMenu1 = FasterWPF.Factory
.BeginMenuSettings(230D, 100D, ContainerType.HorizontalPanel, Brushes.WhiteSmoke)
// .SetItemBorderSettings<Menu>(173D, 20D, Brushes.Silver, new Thickness(1))
.EndMenuSettings();
MenuItemExt.SetMenuOrientationToVertical(subMenu1);
//Step 3: add the individual menuitems to the submenu
MenuItem subMenuItem1 = FasterWPF.Factory
.BeginMenuComposite(225D, 20D, "_Choice #1", subMenu1, Brushes.LightSkyBlue, Brushes.WhiteSmoke, Brushes.Black, Brushes.Black, "Verdana", 10, FontWeights.SemiBold, FontStyles.Normal, Brushes.WhiteSmoke)
.SetMouseOverBorderColor(Brushes.Gray)
.AddMenuItem((o, ev) => { MessageBox.Show("Clicked Choice #1!"); })
.EndMenuComposite();
MenuItem subMenuItem2 = FasterWPF.Factory
.BeginMenuComposite(225D, 20D, "_This is a longer choice", subMenu1, Brushes.LightSkyBlue, Brushes.WhiteSmoke, Brushes.Black, Brushes.Black, "Verdana", 10, FontWeights.SemiBold, FontStyles.Normal, Brushes.WhiteSmoke)
.SetMouseOverBorderColor(Brushes.Gray)
.AddMenuItem((o, ev) => { MessageBox.Show("Clicked 'This is a longer choice.'"); })
.EndMenuComposite();
MenuItem subMenuItem3 = FasterWPF.Factory
.BeginMenuComposite(225D, 20D, "_Edit Vacation Profile", subMenu1, Brushes.LightSkyBlue, Brushes.WhiteSmoke, Brushes.Black, Brushes.Black, "Verdana", 10, FontWeights.SemiBold, FontStyles.Normal, Brushes.WhiteSmoke)
.SetMouseOverBorderColor(Brushes.Gray)
.AddMenuItem((o, ev) => { MessageBox.Show("Clicked 'Edit Vacation Profile.'"); })
.EndMenuComposite();
//Step 4: add the sub-menu to the Border
subMenuBorder.BeginComposite(submnuguid0)
.AddExisting<Menu, Border>(0, 0, subMenu1)
.EndComposite<Border, BorderArgs>(null);
//Step 5: create another main level menu item and add the Border to it via wiring On Click event
//MENU ITEM 2 with Sub-Menu
MenuItem m2 = FasterWPF.Factory
.BeginMenuComposite("_Edit", mnu, Brushes.WhiteSmoke, Brushes.WhiteSmoke, Brushes.Black, Brushes.Black, "Verdana", 12, FontWeights.Bold, FontStyles.Normal, Brushes.WhiteSmoke)
.SetMouseOverBorderColor(Brushes.Gray)
.AddMenuItem((o, ev) =>
{
//b: On click, display sub-menu
MenuItemExt.DisplaySubMenu(cnvs, cnvsguid2, subMenuBorder, 120D, 21D, 500);
MenuItemExt.HideSubMenu(cnvs, cnvsguid3);
})
.EndMenuComposite();
//SUB-MENU 2
//Step 1: create a Border to hold the sub-menu and set it to hide itself on mouse-out
Border subMenuBorder2 = new Border();
subMenuBorder2.Initialize(230D, 27D, ContainerType.HorizontalPanel, Brushes.Gray, new Thickness(1), Brushes.WhiteSmoke);
subMenuBorder2.BeginSettings<Border>().SetItemBorderSettings<Border>(230D, 27D, Brushes.LightGray, new Thickness(1)).EndSettings<Border>();
subMenuBorder2.SubscribeEventOnParent<Border>("MouseLeave",
new MouseEventHandler((o, mse) =>
{
//a: On mouse out, hide sub-menu
MenuItemExt.HideSubMenu(cnvs, cnvsguid3);
}));
//Step 2: create the submenu and set its orientation to vertical
Menu subMenu2 = FasterWPF.Factory
.BeginMenuSettings(230D, 27D, ContainerType.HorizontalPanel, Brushes.WhiteSmoke)
.EndMenuSettings();
MenuItemExt.SetMenuOrientationToVertical(subMenu2);
//Step 3: add the individual menuitems to the submenu
MenuItem subMenu2Item1 = FasterWPF.Factory
.BeginMenuComposite(225D, 20D, "_View Vacation Photos", subMenu2, Brushes.LightSkyBlue, Brushes.WhiteSmoke, Brushes.Black, Brushes.Black, "Verdana", 10, FontWeights.SemiBold, FontStyles.Normal, Brushes.WhiteSmoke)
.SetMouseOverBorderColor(Brushes.Gray)
.AddMenuItem((o, ev) => { MessageBox.Show("Clicked 'View Vacation Photos'"); })
.EndMenuComposite();
//Step 4: add the sub-menu to the Border
subMenuBorder2.BeginComposite(submnuguid1)
.AddExisting<Menu, Border>(0, 0, subMenu2)
.EndComposite<Border, BorderArgs>(null);
//Step 5: create another main level menu item and add the Border to it via wiring On Click event
//MENU ITEM 3
MenuItem m3 = FasterWPF.Factory
.BeginMenuComposite("_View", mnu, Brushes.WhiteSmoke, Brushes.WhiteSmoke, Brushes.Black, Brushes.Black, "Verdana", 12, FontWeights.Bold, FontStyles.Normal, Brushes.WhiteSmoke)
.SetMouseOverBorderColor(Brushes.Gray)
.AddMenuItem((o, ev) =>
{
//b: On click, display sub-menu
MenuItemExt.DisplaySubMenu(cnvs, cnvsguid3, subMenuBorder2, 235D, 21D, 500);
MenuItemExt.HideSubMenu(cnvs, cnvsguid2);
})
.EndMenuComposite();
}
}