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,

  1. 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>
  1. Next, lets create two UserControl views 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>
  1. 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.

WPF Ribbon in MDI Windows

  1. 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 (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 WPF Ribbon Control in child view’s into the MDI parent WPF Ribbon Control 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 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>

WPF Ribbon TDI Merging

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.

View sample in GitHub

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,

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.

WPF Ribbon MDI Merging

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

Changing MergeType in WPF Ribbon Merging

View sample in GitHub

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>

Changing WPF Ribbon Merge Order

View sample in GitHub

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