Ribbon Merge in WPF Ribbon Control
18 Nov 201824 minutes to read
The WPF Ribbon Control allows merging the RibbonTab and RibbonBar of two different WPF Ribbon Controls in MDI applications. DocumentContainer.MDIParentRibbon, RibbonTab.MergeType and RibbonTab.MergeOrder properties helps to perform menu merging.
In WPF, you can create MDI application using WPF Tabbed MDI Form control. Also, WPF Ribbon Control allows to merge RibbonTab and RibbonBar of active child window to the WPF Ribbon Control in parent window.
Creating MDI window and enabling menu merging
The WPF Tabbed MDI Form helps to create MDI window in WPF Application. It allows you to create MDI window and Tabbed MDI window layouts.
Follow the below steps to create simple sample to understand WPF Ribbon Control menu merging,
- Creating main RibbonWindow with WPF Ribbon Control and WPF Tabbed MDI Form
<syncfusion:RibbonWindow xmlns:syncfusion="http://schemas.syncfusion.com/wpf" x:Class="Ribbon.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Ribbon"
mc:Ignorable="d"
WindowStartupLocation="CenterScreen"
xmlns:skin="clr-namespace:Syncfusion.SfSkinManager;assembly=Syncfusion.SfSkinManager.WPF"
skin:SfSkinManager.VisualStyle="Office2019Colorful"
Title="Ribbon Merging" Height="450" Width="700">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<syncfusion:Ribbon x:Name="parentRibbon" >
<syncfusion:RibbonTab Caption="Home">
<syncfusion:RibbonBar Header="Mail">
<syncfusion:RibbonButton Label="New Mail" SizeForm="Large" Click="RibbonButton_Click"/>
</syncfusion:RibbonBar>
</syncfusion:RibbonTab>
</syncfusion:Ribbon>
<syncfusion:DocumentContainer x:Name="doc" Grid.Row="1" >
</syncfusion:DocumentContainer>
</Grid>
</syncfusion:RibbonWindow>- Next, lets create two
UserControlviews with WPF Ribbon Control which acts as child MDI windows.
Child View 1
<UserControl x:Class="Ribbon.ChildView1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Ribbon"
mc:Ignorable="d" xmlns:syncfusion="http://schemas.syncfusion.com/wpf"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<ContentPresenter>
<ContentPresenter.Content>
<Grid>
<syncfusion:Ribbon x:Name="childRibbon" >
<syncfusion:RibbonTab Caption="Home" MergeType="MergeItems">
<syncfusion:RibbonBar Header="Message">
<syncfusion:RibbonButton Label="New Message" SizeForm="Large"/>
<syncfusion:RibbonButton x:Name="MergeButton" Label="Merge" SizeForm="Large" />
<syncfusion:RibbonButton x:Name="UnMergeButton" Label="UnMerge" SizeForm="Large"/>
</syncfusion:RibbonBar>
</syncfusion:RibbonTab>
<syncfusion:RibbonTab Caption="View1 Tab2" >
<syncfusion:RibbonBar Header="Folders">
<syncfusion:RibbonButton Label="New Folder" SizeForm="Large"/>
</syncfusion:RibbonBar>
</syncfusion:RibbonTab>
</syncfusion:Ribbon>
<TextBlock Text="View 1"/>
</Grid>
</ContentPresenter.Content>
</ContentPresenter>
</Grid>
</UserControl>Child View 2
<UserControl x:Class="Ribbon.ChildView2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Ribbon"
mc:Ignorable="d" xmlns:syncfusion="http://schemas.syncfusion.com/wpf"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<ContentPresenter>
<ContentPresenter.Content>
<Grid>
<syncfusion:Ribbon x:Name="childRibbon" >
<syncfusion:RibbonTab Caption="View2 Home" MergeType="AddItems">
<syncfusion:RibbonBar Header="Message">
<syncfusion:RibbonButton Label="View Message" SizeForm="Large"/>
<syncfusion:RibbonButton x:Name="MergeButton" Label="Merge" SizeForm="Large" />
<syncfusion:RibbonButton x:Name="UnMergeButton" Label="UnMerge" SizeForm="Large"/>
</syncfusion:RibbonBar>
</syncfusion:RibbonTab>
<syncfusion:RibbonTab Caption="View2 Tab2" MergeOrder="1">
<syncfusion:RibbonBar Header="Folders">
<syncfusion:RibbonButton Label="New Folder" SizeForm="Large"/>
</syncfusion:RibbonBar>
</syncfusion:RibbonTab>
</syncfusion:Ribbon>
<TextBlock Text="View 2"/>
</Grid>
</ContentPresenter.Content>
</ContentPresenter>
</Grid>
</UserControl>- Now, add the both child view’s into the WPF Tabbed MDI Form and set the the DocumentContainer.MDIParentRibbon property.
<syncfusion:RibbonWindow xmlns:syncfusion="http://schemas.syncfusion.com/wpf" x:Class="Ribbon.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Ribbon"
mc:Ignorable="d"
WindowStartupLocation="CenterScreen"
xmlns:skin="clr-namespace:Syncfusion.SfSkinManager;assembly=Syncfusion.SfSkinManager.WPF"
skin:SfSkinManager.VisualStyle="Office2019Colorful"
Title="Ribbon Merging" Height="450" Width="700">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<syncfusion:Ribbon x:Name="parentRibbon" >
<syncfusion:RibbonTab Caption="Home">
<syncfusion:RibbonBar Header="Mail">
<syncfusion:RibbonButton Label="New Mail" SizeForm="Large" Click="RibbonButton_Click"/>
</syncfusion:RibbonBar>
</syncfusion:RibbonTab>
</syncfusion:Ribbon>
<syncfusion:DocumentContainer x:Name="doc" Grid.Row="1" MDIParentRibbon="{Binding ElementName=parentRibbon}">
<local:ChildView1 x:Name="ChildView1" syncfusion:DocumentContainer.Header="Child View1" syncfusion:DocumentContainer.MDIBounds="150,50,300,230"/>
<local:ChildView2 x:Name="ChildView2" syncfusion:DocumentContainer.Header="Child View2" syncfusion:DocumentContainer.MDIBounds="20,10,300,230"/>
</syncfusion:DocumentContainer>
</Grid>
</syncfusion:RibbonWindow>Now run the application and you can see an output like this.
-
Now the child view’s has been added inside the WPF Tabbed MDI Form, and now lets see how to merge the child WPF Ribbon Control into the parent WPF Ribbon Control.
The merging operation performed based on DocumentContainer.Mode (
MDIandTDI) property.
- MDI - The default value of DocumentContainer.Mode. In the above image child view’s are in MDI mode where each view loaded inside a child window. You can merge the WPF Ribbon Control in child view’s into the MDI parent WPF Ribbon Control by maximizing the MDI child window.

- TDI - The child view’s will be loaded in tabs. In this mode, the child view’s WPF Ribbon Control of the active tab will be merged to the MDI parent WPF Ribbon Control.
In the below example the DocumentContainer.Mode property for WPF Tabbed MDI Form is set to TDI.
<syncfusion:RibbonWindow xmlns:syncfusion="http://schemas.syncfusion.com/wpf" x:Class="Ribbon.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Ribbon"
mc:Ignorable="d"
WindowStartupLocation="CenterScreen"
xmlns:skin="clr-namespace:Syncfusion.SfSkinManager;assembly=Syncfusion.SfSkinManager.WPF"
skin:SfSkinManager.VisualStyle="Office2019Colorful"
Title="Ribbon Merging" Height="450" Width="450">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<syncfusion:Ribbon x:Name="parentRibbon" >
<syncfusion:RibbonTab Caption="Home">
<syncfusion:RibbonBar Header="Mail">
<syncfusion:RibbonButton Label="New Mail" SizeForm="Large" Click="RibbonButton_Click"/>
</syncfusion:RibbonBar>
</syncfusion:RibbonTab>
</syncfusion:Ribbon>
<syncfusion:DocumentContainer x:Name="doc" Grid.Row="1" MDIParentRibbon="{Binding ElementName=parentRibbon}" Mode="TDI">
<local:ChildView1 x:Name="ChildView1" syncfusion:DocumentContainer.Header="Child View1" syncfusion:DocumentContainer.MDIBounds="150,50,300,230"/>
<local:ChildView2 x:Name="ChildView2" syncfusion:DocumentContainer.Header="Child View2" syncfusion:DocumentContainer.MDIBounds="20,10,300,230"/>
</syncfusion:DocumentContainer>
</Grid>
</syncfusion:RibbonWindow>In the image notice that Child View1 tab is selected and elements of selected child view’s WPF Ribbon Control are merged into the MDI parent WPF Ribbon Control.
Merge Type
RibbonTab.MergeType property indicates how the items in child view’s WPF Ribbon Control are merged with MDI parent WPF Ribbon Control. MergeType has following options,
-
Add - Adds the child view’s RibbonTab to the MDI parent WPF Ribbon Control based on RibbonTab.MergeOrder, even if MDI parent has RibbonTab with same Caption.
-
Merge - The default value of RibbonTab.MergeType. If RibbonTab.Caption of MDI parent WPF Ribbon Control and RibbonTab.Caption of child view’s WPF Ribbon Control has same name and child view’s RibbonTab.MergeType is Merge, then child view’s RibbonBar’s are merged with MDI parent’s tab. If MDI parent WPF Ribbon Control doesn’t have tab with same caption, then child view’s WPF Ribbon Control tab added to MDI parent WPF Ribbon Control based on RibbonTab.MergeOrder.
Let’s look at the example,
In the example both the MDI parent WPF Ribbon Control and child view1’s WPF Ribbon Control has RibbonTab with same caption and the default value of MergeType is Merge. So, when child view1 maximized, bar’s in child view’s Home tab get are merged to MDI parent ribbon’s Home tab.

If you change the MergeType of RibbonTab in child view1 as Add, then Home tab will be added as new tab like View1 Tab2

Merge Order
MDI parent WPF Ribbon Control positions the child view’s RibbonTabs followed by the tabs of MDI parent WPF Ribbon Control. You can change the position of child view’s WPF Ribbon Control using RibbonTab.MergeOrder property.
In the below code, the RibbonTab.MergeOrder for View2 Tab2 is set as 1. So, the RibbonTab is positioned at 1st index while merging to MDI parent.
<UserControl x:Class="Ribbon.ChildView2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Ribbon"
mc:Ignorable="d" xmlns:syncfusion="http://schemas.syncfusion.com/wpf"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<ContentPresenter>
<ContentPresenter.Content>
<Grid>
<syncfusion:Ribbon x:Name="childRibbon" >
<syncfusion:RibbonTab Caption="View2 Home" MergeType="AddItems">
<syncfusion:RibbonBar Header="Message">
<syncfusion:RibbonButton Label="View Message" SizeForm="Large"/>
<syncfusion:RibbonButton x:Name="MergeButton" Label="Merge" SizeForm="Large" />
<syncfusion:RibbonButton x:Name="UnMergeButton" Label="UnMerge" SizeForm="Large"/>
</syncfusion:RibbonBar>
</syncfusion:RibbonTab>
<syncfusion:RibbonTab Caption="View2 Tab2" MergeOrder="1">
<syncfusion:RibbonBar Header="Folders">
<syncfusion:RibbonButton Label="New Folder" SizeForm="Large"/>
</syncfusion:RibbonBar>
</syncfusion:RibbonTab>
</syncfusion:Ribbon>
<TextBlock Text="View 2"/>
</Grid>
</ContentPresenter.Content>
</ContentPresenter>
</Grid>
</UserControl>Merging and Unmerging in code
WPF Ribbon Control merging can be performed in code by using Ribbon.Merge method of MDI parent WPF Ribbon Control. Child view’s WPF Ribbon Control should be passed as parameter to perform merge operation.
Similarly, the child WPF Ribbon Control can be unmerged from MDI parent WPF Ribbon Control using Ribbon.UnMerge method of MDI parent WPF Ribbon Control.
public MainWindow()
{
InitializeComponent();
this.Child1.MergeButton.Click += MergeButton_Click;
this.Child1.UnMergeButton.Click += UnMergeButton_Click;
}
private void UnMergeButton_Click(object sender, RoutedEventArgs e)
{
this.parentRibbon.UnMerge(this.Child1.childRibbon);
}
private void MergeButton_Click(object sender, RoutedEventArgs e)
{
this.parentRibbon.Merge(this.Child1.childRibbon);
}Public Sub New()
InitializeComponent()
Me.Child1.MergeButton.Click += AddressOf MergeButton_Click
Me.Child1.UnMergeButton.Click += AddressOf UnMergeButton_Click
End Sub
Private Sub UnMergeButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
Me.parentRibbon.UnMerge(Me.Child1.childRibbon)
End Sub
Private Sub MergeButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
Me.parentRibbon.Merge(Me.Child1.childRibbon)
End Sub