wpf-9155-controls-and-libraries-layout-management-dock-windows-mdi-bar-merging.md
You can implement Multiple-Document Interface (MDI) mode in your applications that use the DocumentGroup and DocumentPanel objects.
The DocumentGroup and each of its child DocumentPanels can have its own menus, bars and ribbons. To avoid duplicating these toolbars/ribbons, you can merge them from child into parent windows.
Run Demo: MDI Ribbon Merging Demo
As an example, the DocumentGroup‘s menu can have general commands that work with files, windows, and its child panels can have bars and menus that perform panel-specific actions. In this case, you can merge a child panel’s menus and bars into the parent’s menus and bars when the panel is expanded.
View Example: Merge Bars in MDI Mode
The merging mechanism uses the following item’s properties to match items from the parent and child bars:
Use the BarItemLinkBase.MergeType property to select a merge type. You should specify this property only for a child BarManager’s items and links that you want to merge. You can choose one of the following merge types:
The bar item links of a child BarManager’s bar/link container are added to the parent BarManager’s bar/link container (the default behavior).
Show Code
<Grid>
<DockPanel>
<!-- Parent Bar Items -->
<dxb:MainMenuControl Caption="File" DockPanel.Dock="Top">
<dxb:MainMenuControl.Items>
<dxb:BarButtonItem
Content="Open"
ItemClick="parent_bar_open"
MergeOrder="0" />
<dxb:BarButtonItem
Content="Save"
ItemClick="parent_bar_save"
MergeOrder="1" />
<dxb:BarButtonItem
Content="MDI"
ItemClick="biMDI_ItemClick"
MergeOrder="3" />
<dxb:BarButtonItem
Content="Tabbed"
ItemClick="biTabbed_ItemClick"
MergeOrder="4" />
</dxb:MainMenuControl.Items>
</dxb:MainMenuControl>
<Grid>
<dxdo:DockLayoutManager x:Name="dlManager">
<dxdo:LayoutGroup>
<dxdo:DocumentGroup>
<dxdo:DocumentPanel>
<Grid>
<DockPanel>
<!-- Child Bar Items -->
<dxb:MainMenuControl Caption="File" DockPanel.Dock="Top">
<dxb:BarButtonItem Content="Open"
MergeOrder="0" MergeType="Add" />
<dxb:BarButtonItem Content="Save"
MergeOrder="1" MergeType="Add" />
<dxb:BarButtonItem Content="Close" MergeOrder="2" />
</dxb:MainMenuControl>
<!-- ... -->
</DockPanel>
</Grid>
</dxdo:DocumentPanel>
</dxdo:DocumentGroup>
</dxdo:LayoutGroup>
</dxdo:DockLayoutManager>
</Grid>
</DockPanel>
</Grid>
This setting is applied to link the following containers: Bar, BarSubItem, PopupMenu, BarLinkContainerItem.
When this setting is applied, the child container’s links are merged into the parent container with the same caption. If the captions of these containers are different, the child container’s links are added to the parent container (similar to the Add setting).
Show Code
<Grid>
<DockPanel>
<!-- Parent Bar Items -->
<dxb:MainMenuControl Caption="File" DockPanel.Dock="Top">
<dxb:MainMenuControl.Items>
<dxb:BarSubItem Content="File">
<dxb:BarSubItem.Items>
<dxb:BarButtonItem
Content="Open"
ItemClick="parent_bar_open"
MergeOrder="0" />
<dxb:BarButtonItem
Content="Save"
ItemClick="parent_bar_save"
MergeOrder="1" />
<dxb:BarButtonItem Content="MDI" MergeOrder="3" />
<dxb:BarButtonItem Content="Tabbed" MergeOrder="4" />
</dxb:BarSubItem.Items>
</dxb:BarSubItem>
</dxb:MainMenuControl.Items>
</dxb:MainMenuControl>
<Grid>
<dxdo:DockLayoutManager x:Name="dlManager">
<dxdo:LayoutGroup>
<dxdo:DocumentGroup>
<dxdo:DocumentPanel>
<Grid>
<DockPanel>
<!-- Child Bar Items -->
<dxb:MainMenuControl Caption="File" DockPanel.Dock="Top">
<dxb:MainMenuControl.Items>
<dxb:BarSubItem Content="File" MergeType="MergeItems">
<dxb:BarButtonItem
Content="Open"
ItemClick="child_bar_open"
MergeOrder="0"
MergeType="Replace" />
<dxb:BarButtonItem
Content="Save"
ItemClick="child_bar_save"
MergeOrder="1"
MergeType="Replace" />
<dxb:BarButtonItem Content="Close" MergeOrder="2" />
</dxb:BarSubItem>
</dxb:MainMenuControl.Items>
</dxb:MainMenuControl>
<!-- ... -->
</DockPanel>
</Grid>
</dxdo:DocumentPanel>
</dxdo:DocumentGroup>
</dxdo:LayoutGroup>
</dxdo:DockLayoutManager>
</Grid>
</DockPanel>
</Grid>
The bar item links of a child BarManager’s bar/link container with identical captions are removed from the parent bar.
Show Code
<Grid>
<DockPanel>
<!-- Parent Bar Items -->
<dxb:MainMenuControl Caption="File" DockPanel.Dock="Top">
<dxb:MainMenuControl.Items>
<dxb:BarButtonItem Content="Open" MergeOrder="0" ItemsClick="parent_bar_open" />
<dxb:BarButtonItem Content="Save" MergeOrder="1" ItemsClick="parent_bar_save" />
<dxb:BarButtonItem Content="MDI" MergeOrder="3" />
<dxb:BarButtonItem Content="Tabbed" MergeOrder="4" />
</dxb:MainMenuControl.Items>
</dxb:MainMenuControl>
<Grid>
<dxdo:DockLayoutManager x:Name="dlManager">
<dxdo:LayoutGroup>
<dxdo:DocumentGroup>
<dxdo:DocumentPanel>
<Grid>
<DockPanel>
<!-- Child Bar Items -->
<dxb:MainMenuControl Caption="File" DockPanel.Dock="Top">
<dxb:BarButtonItem Content="Open"
ItemsClick="child_bar_open" MergeOrder="0" MergeType="Remove" />
<dxb:BarButtonItem Content="Save"
ItemsClick="child_bar_save" MergeOrder="1" MergeType="Remove" />
<dxb:BarButtonItem Content="Close" MergeOrder="2" />
</dxb:MainMenuControl>
<!-- ... -->
</DockPanel>
</Grid>
</dxdo:DocumentPanel>
</dxdo:DocumentGroup>
</dxdo:LayoutGroup>
</dxdo:DockLayoutManager>
</Grid>
</DockPanel>
</Grid>
The bar item links of a child BarManager’s bar/link container replace item links on the parent bar with identical captions.
Show Code
<Grid>
<DockPanel>
<!-- Parent Bar Items -->
<dxb:MainMenuControl Caption="File" DockPanel.Dock="Top">
<dxb:MainMenuControl.Items>
<dxb:BarButtonItem Content="Open" MergeOrder="0" ItemClick="parent_bar_open" />
<dxb:BarButtonItem Content="Save" MergeOrder="1" ItemClick="parent_bar_save" />
<dxb:BarButtonItem Content="MDI" MergeOrder="3" />
<dxb:BarButtonItem Content="Tabbed" MergeOrder="4" />
</dxb:MainMenuControl.Items>
</dxb:MainMenuControl>
<Grid>
<dxdo:DockLayoutManager x:Name="dlManager">
<dxdo:LayoutGroup>
<dxdo:DocumentGroup>
<dxdo:DocumentPanel>
<Grid>
<DockPanel>
<!-- Child Bar Items -->
<dxb:MainMenuControl Caption="File" DockPanel.Dock="Top">
<dxb:BarButtonItem Content="Open"
ItemsClick="child_bar_open" MergeOrder="0" MergeType="Replace" />
<dxb:BarButtonItem Content="Save"
ItemsClick="child_bar_save" MergeOrder="1" MergeType="Replace" />
<dxb:BarButtonItem Content="Close" MergeOrder="2" />
</dxb:MainMenuControl>
<!-- ... -->
</DockPanel>
</Grid>
</dxdo:DocumentPanel>
</dxdo:DocumentGroup>
</dxdo:LayoutGroup>
</dxdo:DockLayoutManager>
</Grid>
</DockPanel>
</Grid>
Each merged bar/menu link has the MergeOrder property that specifies the order in which parent and child bar elements are displayed in the merged bar.
Links with the lowest MergeOrder are displayed first. The last few links are those that have the greatest MergeOrder value.
If a parent and child BarManager’s links have equal MergeOrder values, the parent BarManager’s links are placed first, and then the child BarManager’s links are placed.
A panel’s bar items can be embedded into the a ThemedWindow‘s ToolbarItems / HeaderItems bar collections. If a ThemedWindow‘s bar is defined in ToolbarItems or HeaderItems, the panel merges its control box buttons with this bar. If a ThemedWindow contains a bar both in ToolbarItems and HeaderItems, the panel merges its control box buttons with HeaderItems.
Handle the following events to merge or unmerge a bar/menu:
| Event | Description |
|---|---|
| DockLayoutManager.Merge | Allows you to customize menus and bars when the merging mechanism is invoked. |
| DockLayoutManager.UnMerge | Allows you to undo bars customizations performed via the DockLayoutManager.Merge event. This event also allows you to undo the results of the manual merge operation that you performed with the DockLayoutManager.Merge event handler. |
When you populate a bar with items from a ViewModel collection, you should populate a bar and then merge another bar with it. To do this, disable the automatic merging and manually merge bars when they are loaded.
Call the parent bar’s Merge method to merge two bars that belong to different BarManagers.
After bars are merged, you can call any of the Bar.UnMerge methods to restore the original bars/menus layout.
Call the ILinksHolder.Merge and ILinksHolder.UnMerge methods to merge/unmerge menus of containers that implement the ILinksHolder interface.
Set the panel’s ElementMergingBehavior attached property to None to disable toolbar merging for the panel:
<Window ...
xmlns:dxdo="http://schemas.devexpress.com/winfx/2008/xaml/docking">
<dxdo:DockLayoutManager>
<dxdo:LayoutGroup>
<dxdo:DocumentGroup>
<dxdo:DocumentPanel Caption="Document1" dxb:MergingProperties.ElementMergingBehavior="None">
<!-- ... -->
</dxdo:DocumentPanel>
<dxdo:DocumentPanel Caption="Document2"/>
</dxdo:DocumentGroup>
</dxdo:LayoutGroup>
</dxdo:DockLayoutManager>
</Window>
You can use the following properties to customize a toolbar merge:
ElementMergingBehaviorGets or sets whether the current container’s elements are merged with elements of outside containers or elements of the same container or both. Also allows you to disable merging. This is an attached property.ToolBarMergeStyleGets or sets the type of controls for which automatic merging is enabled. This is an attached property.NameGets or sets a “merge name”. This is an attached property.
As with the bars and menus, you can merge a child panel with a parent group’s RibbonControls.
You can merge the following elements:
View Example: Merge Ribbon Controls in MDI Mode
The Merging mechanism uses the following item’s properties to match items from the parent and child ribbons:
Use the MergeType property to select a merge type. You should specify this property only for a child ribbon’s items and links that you want to merge. You can choose one of the following merge types:
| Ribbon Element | Property |
|---|---|
| RibbonPageCategory | RibbonPageCategoryBase.MergeType |
| RibbonPage | RibbonPage.MergeType |
| RibbonPageGroup | RibbonPageGroup.MergeType |
| BarItemLinkBase | BarItemLinkBase.MergeType |
You can choose one of the following merge types:
| Value | Description |
|---|---|
| Add | The ribbon items of a child ribbon are added to the parent ribbon (the default behavior). |
| MergeItems | The default merging mechanism. Sub-items of the current child ribbon element are merged into the parent ribbon element that has the same caption. If no parent element with the same caption exists, the current child ribbon element is appended according to its MergeOrder. |
| Remove | The ribbon items of a child ribbon with identical captions are removed from a merged ribbon. |
| Replace | The ribbon items of a child ribbon replace ribbon items on the parent ribbon with identical captions. |
Each merged element has the MergeOrder property that specifies the order in which parent/child ribbon’s items are displayed in the merged ribbon.
The first element’s MergeOrder is 0. An element with the greatest MergeOrder value is the last. The default MergeOrder value for all elements is 0.
If parent and child ribbons include items with equal MergeOrder property values, the child ribbon’s items are placed after all parent ribbon’s items with that MergeOrder.
You can use the following properties to specify the merge order of different elements of a ribbon:
| Property | Description |
|---|---|
| RibbonPageCategory | RibbonPageCategoryBase.MergeOrder |
| RibbonPage | RibbonPage.MergeOrder |
| RibbonPageGroup | RibbonPageGroup.MergeOrder |
| BarItemLinkBase | BarItemLinkBase.MergeOrder |
The Ribbon control merges and arranges its elements in the following order:
<!-- The parent Ribbon Control: -->
<dxr:RibbonPage MergeOrder="0" Caption="Home" Name="mainHomePage">
<!-- ... -->
</dxr:RibbonPage>
<dxr:RibbonPage MergeOrder="2" Caption="View" Name="mainViewPage">
<!-- ... -->
</dxr:RibbonPage>
<!-- The child Ribbon Control: -->
<dxr:RibbonPage MergeOrder="1" Caption="Insert" Name="child2InsertPage">
<!-- ... -->
</dxr:RibbonPage>
<dxr:RibbonPage MergeOrder="4" Caption="Add-ins" Name="child2AddInsPage">
<!-- ... -->
</dxr:RibbonPage>
<dxr:RibbonPage MergeOrder="3" Caption="Test" Name="child2TestPage">
<!-- ... -->
</dxr:RibbonPage>
The following image demonstrates a merge result:
Call the RibbonControl.UnMerge / RibbonStatusBarControl.UnMerge methods to unmerge RibbonControl / RibbonStatusBarControl.
If you merged multiple Ribbon objects, you can define which child Ribbon object should be unmerged from the parent object.
To restore the parent control’s layout, call an Unmerge method without parameters.
Menus, bars, and ribbons are merged in the following cases:
Menus, bars, and ribbons are unmerged in the following cases:
You can use the DockLayoutManager.MDIMergeStyle property to change the default bar merging behavior. This property affects all child panels within a DockLayoutManager. You can choose one of the following values:
The panel’s bar/ribbon is merged with the parent bar/ribbon in the following cases:
If your layout contains multiple DocumentGroups, the merging mechanism is invoked for all DocumentGroups simultaneously. In this case, all of them are merged to the parent at the same time.
Bars/ribbons are unmerged in the following cases:
NeverPrevents all child tabbed and MDI panels from being merged.WhenChildActivated
Bars/ribbons are merged in the following cases:
Bars/ribbons are unmerged in the following cases:
WhenLoadedOrChildActivatedSimilar to WhenChildActivated mode, but additionally merges MDI panels and tabs that are initially maximized (docked), but not yet selected (for example, on application start).
Use the DocumentPanel.MDIMergeStyle attached property to specify the merge behavior for the panel. This property has a higher priority than the DockLayoutManager.MDIMergeStyle property.
Bars and Ribbons included in LayoutPanels are not merged with the parent container (the default behavior).
Set the LayoutPanel bar/ribbon’s ElementMergingBehavior property to InternalWithExternal to merge a LayoutPanel‘s bars/ribbons with a parent container:
<Style TargetType="dxdo:LayoutPanel">
<Setter Property="dxb:MergingProperties.ElementMergingBehavior" Value="InternalWithExternal" />
</Style>
See Also