Ribbon Merge in WPF Ribbon

9 Aug 202324 minutes to read

WPF Ribbon allows merging of RibbonTab and RibbonBar of two different 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 DocumentContainer control. Also, Ribbon controls allows to merge RibbonTab and RibbonBar of active child window to the Ribbon in parent window.

Creating MDI window and enabling menu merging

DocumentContainer helps to create MDI window in WPF Application. The DocumentContainer allows you to create MDI window and Tabbed MDI window layouts.

Follow the below steps to create simple sample to understand ribbon menu merging,

  1. Creating main RibbonWindow with Ribbon and DocumentContainer
<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>
  1. Next, lets create two UserControl views with Ribbon 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>
  1. Now, add the both child view’s into the DocumentContainer and set the the DocumentContainer.MDIParentRibbon property of DocumentContainer.
<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.

WPF Ribbon in MDI Windows

  1. Now the child view’s has been added inside the DocumentContainer, and now lets see how to merge the child Ribbon into the parent Ribbon.

    The merging operation performed based on DocumentContainer.Mode (MDI and TDI) 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 Ribbon in child view’s into the MDI parent Ribbon by maximizing the MDI child window.

WPF Ribbon MDI Merging

  • TDI - The child view’s will be loaded in tabs. In this mode, the child view’s ribbon of the active tab will be merged to the MDI parent Ribbon.

In the below example the DocumentContainer.Mode property for DocumentContainer 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>

WPF Ribbon TDI Merging

In the image notice that Child View1 tab is selected and elements of selected child view’s ribbon are merged into the MDI parent Ribbon.

NOTE

View sample in GitHub

Merge Type

RibbonTab.MergeType property indicates how the items in child view’s ribbon are merged with MDI parent ribbon. MergeType has following options,

Let’s look at the example,

In the example both the MDI parent ribbon and child view1’s ribbon has ribbon tab 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.

WPF Ribbon MDI Merging

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

Changing MergeType in WPF Ribbon Merging

NOTE

View sample in GitHub

Merge Order

MDI parent ribbon positions the child view’s ribbon tabs followed by the tabs of MDI parent ribbon. You can change the position of child view’s ribbon using RibbonTab.MergeOrder property.

In the below code, the RibbonTab.MergeOrder for View2 Tab2 is set as 1. So, the ribbon tab 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>

Changing WPF Ribbon Merge Order

NOTE

View sample in GitHub

Merging and Unmerging in code

Ribbon merging can be performed in code by using Ribbon.Merge method of MDI parent ribbon. Child view’s ribbon should be passed as parameter to perform merge operation.

Similarly, the child ribbon can be unmerged from MDI parent ribbon using Ribbon.UnMerge method of MDI parent ribbon.

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