Home » Programming » WPF » WPF Ribbon » WPF Ribbon (CTP) – Part 1 – Add Ribbon and Customize

WPF Ribbon (CTP) – Part 1 – Add Ribbon and Customize

The ribbon-like look and feel seems to be a general trend. Once we got used with look and feel of the Office applications, we might as well want to use it our own applications.

For .NET users, the ribbon is accesible using MFC Feature Pack or the WPF CTP release. I will focus on the WPF version, which can be found on wpf.codeplex.com, where you can find a discussion list and an issue traker list. Being the CTP release, there still are some known issues and some of the controls that you normally have in an Office application are not yet available (for exemple Color Picker, Color Button, Gallery etc), but hopefully this things will be solved when the Ribbon V1 will be available.

After you downloaded the WPF Ribbon binaries, you can start creating your first application that uses the ribbon.

Minimum requirements for this tutorial:

  • Visual Studio 2008 SP1 and .NET Framework 3.5 – needed for this version of ribbon to work; in .Net Framework 4.0 a better version for the WPF ribbon will be available.
  • Basic knowledge about WPF and bindings

Entire Tutorial:

Summary

  • Step1: Creating a new WPF Application Project
  • Step 2: Including the RibbonControlsLibrary.dll
  • Step 3: Adding the Ribbon inside the main window
  • Step 4: Customizing the Ribbon
  • Step 5: Adding images as resources to the project
  • Step 6a: Defining the RibbonApplicationMenu from XAML
  • Step 6b: Defining the RibbonApplicationMenuItem from Code Behind
    • Loading an image from code behind
    • Creating a RibbonCommand from code behind
  • Step 7: Defining a RibbonSeparator in XAML
  • Step 8: Defining a RibbonApplicationSplitMenuItem in XAML
  • Step 9: Defining the RibbonApplicationMenu.RecentItemList
  • Step 10: Defining the Quick Access Toolbar (QAT)
  • Step 11: Removing the titlebar

A Ribbon Example

Step 1: Creating a new WPF Application Project

First of all, you should create a new WPF project: Open Visual Studio and select File -> New -> Project. From the available WPF project types select WPF Application and name the solution WPFRibbonExample.

Step 2: Including the RibbonControlsLibrary.dll

Now, you have to include the Ribbon Dll. In Solution Explorer window, right click the WPFRibbonExample project and select Add Reference and then browse for the RibbonControlsLibrary.dll file. I would recommend storing it in a folder close to the project or even inside the project, in an “Include” file – this way you will have it referenced even if you move the solution folder on a different computer.

Step 3: Adding the Ribbon inside the main window

The first thing we have to do is to create a namespace for the RibbonControlsLibrary dll in order to use the Ribbon controls. So, let’s suppose that the namespace inside the window1.xaml file would be ‘ribbon‘, then we would have this declaration inside the Window tag:

xmlns:ribbon="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"

In this way, every time we want to use a control from this dll, we have to postfix the tag name with ribbon:, for example, if we want to use the RibbonTextBox, we will use <ribbon:RibbonTextBox/>

The next step is to add the ribbon on the window, so right now we would have this code in the Window1.xaml file:

<Window x:Class="WPFRibbonExample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ribbon="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"
Title="Window1">
  <Grid>
    <ribbon:Ribbon>
    </ribbon:Ribbon>
  </Grid>
</Window>

And the preview of the window would look like this:

Well, it certainly looks incomplete, so we have to define some more elements for this ribbon, like the application menu and tabs.

Step 4: Customizing the Ribbon

By default, the style and theme of the application are inherited from the operating system (in my case Windows 7). We can also set the application to have the Office blue style, by adding inside the Window tag the following resource:

<Window.Resources>
  <ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
      <ResourceDictionary Source="/RibbonControlsLibrary;component/Themes/Office2007Blue.xaml"/>
    </ResourceDictionary.MergedDictionaries>
  </ResourceDictionary>
</Window.Resources>

You could also use the Office2007Silver.xaml or Office2007Black.xaml.

Step 5: Adding images as resources to the project

We have to add some images resources to the project, in order to use them in our example application. Create a new folder inside the project and name it images. In this folder we will add as many images as we want, but for now, let’s just add 3 images: globe.png, positive-icon16.png and positive-icon32.png. Make sure that each of these images are included in the project and the build action is set to ‘resource’, otherwise the application will crash as it cannot load the images.

Step 6a: Defining the RibbonApplicationMenu from XAML

Now, we are ready to add the Application Menu and an example menu option. The code will look like this:

<Window x:Class="WPFRibbonExample.Window1"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:ribbon="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"
 Title="WPF Ribbon Example">
 <Window.Resources>
   <ResourceDictionary>
     <ResourceDictionary.MergedDictionaries>
       <ResourceDictionary Source="/RibbonControlsLibrary;component/Themes/Office2007Blue.xaml"/>
     </ResourceDictionary.MergedDictionaries>

     <ribbon:RibbonCommand x:Key="ApplicationMenuCommand"
         LargeImageSource="images/globe.png"/>

     <ribbon:RibbonCommand x:Key="ExampleCommand" x:Name="ExampleCommand"
         Executed="ExampleCommand_Executed"
         LabelTitle="Example Label Title"
         LabelDescription="Example Label Description"
         ToolTipDescription="Example Tool Tip Description"
         ToolTipFooterDescription="Example Tool Tip Footer Description"
         ToolTipFooterImageSource="images/positive-icon16.png"
         ToolTipFooterTitle="Example Tool Tip Footer Title"
         ToolTipImageSource="images/positive-icon32.png"
         ToolTipTitle="Example Tool Tip Title"
         LargeImageSource="images/positive-icon32.png"
         SmallImageSource="images/positive-icon16.png"
        />
    </ResourceDictionary>
  </Window.Resources>
  <Grid>
    <ribbon:Ribbon>
      <ribbon:Ribbon.ApplicationMenu>
        <ribbon:RibbonApplicationMenu Command="{StaticResource ApplicationMenuCommand}">
          <ribbon:RibbonApplicationMenu.Items>
            <ribbon:RibbonApplicationMenuItem Name="ExampleMenuItem" Command="{StaticResource ExampleCommand}" ></ribbon:RibbonApplicationMenuItem>
          </ribbon:RibbonApplicationMenu.Items>
        </ribbon:RibbonApplicationMenu>
      </ribbon:Ribbon.ApplicationMenu>
    </ribbon:Ribbon>
  </Grid>
</Window>

As you can see, inside the Ribbon, we have a RibbonApplicationMenu, which contains RibbonApplicationMenuItems. If we run the application, we will be able to distinguish visually which is which:

Both RibbonApplicationMenu and RibbonApplicationMenuItem have an associated Command. This is a specific feature for the WPF Ribbon. Using the Ribbon Command, you can specify the label, image or tooltip for any ribbon control, through these properties:

  • Executed – this event handler needs to be specified in order for the control to be enabled. If it is missing, the control will be disabled. If you define the RibbonCommand from code behind you should set the CanExecute flag to true (see the example below)
  • LabelTitle – the label that will be displayed on the control (for example: the text on a button, the text on the menu item etc)
  • LabelDescription – the label description
  • ToolTipDescription – the tool tip description
  • ToolTipFooterDescription – the description in the footer of the tool tip
  • ToolTipFooterImageSource – the image in the tool tip footer; if missing, there will be no image displayed and the user will see some empty space where the image should have been; this image can be any size (16×16, 32×32)
  • ToolTipFooterTitle – the title of the tool tip footer
  • ToolTipImageSource – the image on the tool tip; if missing, there will be no image displayed and the user will see some empty space where the image should have been; this image can be any size (16×16, 32×32)
  • ToolTipTitle – the title of the tooltip
  • LargeImageSource – the image to be displayed when the control is Large; if missing, there will be no image displayed and the user will see some empty space where the image should have been. Usually, the LargeImageSource is a 32×32 image.
  • SmallImageSource – the image to be displayed when the control is Small; if missing, there will be no image displayed and the user will see some empty space where the image should have been. Usually, the SamllImageSource is a 16×16 image.

Step 6b: Defining the RibbonApplicationMenuItem from Code Behind

Loading an image from code behind

You can create an identical menu item from code behind too, but there is an additional aspect you should consider: loading an image in code behind on a ribbon control. The XAML is checked at compile time and if the resource does not exist, you will get an error. But in the code behind, the image source specified is not verified at compile time, but at run-time. So you might want to load an image, and actually see none. Thus, you have to be very careful in specifying relative paths and transforming them into absolute paths. Take the following code snippet for example:

 /// <summary>
 /// Gets the BitmapImage for the specified relativeSource
 /// </summary>
 /// <param name="relativeSource">The image path relative to the project. For example: /images/globe.png</param>
 /// <returns></returns>
 private BitmapImage GetImage(string relativeUri)
 {
   BitmapImage bmp = new BitmapImage();
   try
   {
      bmp.BeginInit();
      bmp.UriSource = new Uri(relativeUri, UriKind.Relative);
      bmp.EndInit();
   }
   catch (Exception ex)
   {
     Debug.WriteLine(string.Format("Exception:{0} ... StackTrace:{1}", ex.Message, ex.StackTrace));
   }
   return bmp;
 }

Let’s suppose that you want to load the globe.png image, which is situated inside the image folder inside the project. When you call this method you should specify the parameter as the relative path “/images/globe.png“. This way, when rendering the image, the application will know to generate the absolute path (something like: “pack://application:,,,/images/globe.png“) and display the proper image.

Creating a RibbonCommand from code behind

So, let’s suppose we have another RibbonApplicationMenuItem, named CodeBehindMenuItem, with no associated command:

<ribbon:RibbonApplicationMenuItem Name="CodeBehindMenuItem"></ribbon:RibbonApplicationMenuItem>

Using the previous method for image loading, we can specify the command from code behind:

private void SetCodeBehindCommand()
{
  RibbonCommand command = new RibbonCommand();
  command.CanExecute += new CanExecuteRoutedEventHandler(command_CanExecute);
  command.LabelDescription = "Code behind label description";
  command.LabelTitle = "Code behind label title";
  command.LargeImageSource = GetImage("/images/positive-icon32.png");
  command.SmallImageSource = GetImage("/images/positive-icon16.png");
  command.ToolTipDescription = "Code behind label description";
  command.ToolTipFooterDescription = "Code behind label description";
  command.ToolTipFooterImageSource = GetImage("/images/positive-icon16.png");
  command.ToolTipFooterTitle = "Code behind label description";
  command.ToolTipImageSource = GetImage("/images/positive-icon32.png");
  command.ToolTipTitle = "Code behind Tool Tip Title";
  // associate the command with the menu item
  CodeBehindMenuItem.Command = command;
}

void command_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
  // set to true in order to enable the control
  e.CanExecute = true;
}

Step 7: Defining a RibbonSeparator in XAML

If you can group the menu items in the ribbon application menu, you might need a separator. Adding such a control is rather easy. All you have to to is add the following line inside the ribbon:RibbonApplicationMenu.Items tag

<ribbon:RibbonSeparator></ribbon:RibbonSeparator>

Step 8: Defining a RibbonApplicationSplitMenuItem in XAML

The RibbonApplicationSplitMenuItem allows you to define a submenu for a certain menuItem, much like the “Save As” MenuItem in Office. This can be done by adding the RibbonApplicationSplitMenuItem with the containing RibbonApplicationSplitMenuItem or RibbonApplicationMenuItem inside the ribbon:RibbonApplicationMenu.Items tag, like this:

<ribbon:RibbonApplicationSplitMenuItem Command="{StaticResource RibbonApplicationSplitMenuItem}>
  <ribbon:RibbonApplicationMenuItem Command="{StaticResource RibbonApplicationSplitMenuItem1}"/>
  <ribbon:RibbonApplicationMenuItem Command="{StaticResource RibbonApplicationSplitMenuItem2}"/>
</ribbon:RibbonApplicationSplitMenuItem>

Of course, we have to define commands and event handlers in code behind for them:

<ribbon:RibbonCommand x:Key="RibbonApplicationSplitMenuItem" x:Name="RibbonApplicationSplitMenuItem"
 Executed="RibbonApplicationSplitMenuItem_Executed"
 LabelTitle="Ribbon Application Split Menu Item"
 LabelDescription="Ribbon Application Split Menu Item - Subitems"
 LargeImageSource="images/positive-icon32.png"
 SmallImageSource="images/positive-icon16.png"
 />

 <ribbon:RibbonCommand x:Key="RibbonApplicationSplitMenuItem1" x:Name="RibbonApplicationSplitMenuItem1"
 Executed="RibbonApplicationSplitMenuItem_Executed"
 LabelTitle="Subitem 1 Label Title"
 LabelDescription="Subitem 1 Label Description"
 LargeImageSource="images/positive-icon32.png"
 SmallImageSource="images/positive-icon16.png"
 />

 <ribbon:RibbonCommand x:Key="RibbonApplicationSplitMenuItem2" x:Name="RibbonApplicationSplitMenuItem2"
 Executed="RibbonApplicationSplitMenuItem_Executed"
 LabelTitle="Subitem 2 Label Title"
 LabelDescription="Subitem 2 Label Description"
 LargeImageSource="images/positive-icon32.png"
 SmallImageSource="images/positive-icon16.png"
 />

Now, the application looks like this:

As you can see, the title of the submenu is actually the LabelDescription of the RibbonApplicationSplitMenuItem.

Step 9: Defining the RibbonApplicationMenu.RecentItemList

The ribbon application menu has by default an area for the recent items list, in the right part of the application menu. You can choose how you want this area to look like and even dynamically populate it with the corresponding elements. Inside the <ribbon:RibbonApplicationMenu>, you can define the recent item list. For this example I considered it a StackPanel, with the “Recent Files” header, a separator and a list of three RibbonHighlightingListItems. If you want, you can also generate dynamically the list of recent files, from code behind, by using the lstRecentItems control.

<ribbon:RibbonApplicationMenu.RecentItemList>
  <StackPanel>
    <ribbon:RibbonLabel>Recent Files</ribbon:RibbonLabel>
    <ribbon:RibbonSeparator/>
    <ribbon:RibbonHighlightingList x:Name="lstRecentItems">
      <ribbon:RibbonHighlightingList.Items>
        <ribbon:RibbonHighlightingListItem Content="RibbonHighlightingListItem 1 Content"></ribbon:RibbonHighlightingListItem>
        <ribbon:RibbonHighlightingListItem Content="RibbonHighlightingListItem 2 Content"></ribbon:RibbonHighlightingListItem>
        <ribbon:RibbonHighlightingListItem Content="RibbonHighlightingListItem 3 Content"></ribbon:RibbonHighlightingListItem>
      </ribbon:RibbonHighlightingList.Items>
    </ribbon:RibbonHighlightingList>
  </StackPanel>
</ribbon:RibbonApplicationMenu.RecentItemList>

Step 10: Defining the Quick Access Toolbar (QAT)

Inside the ribbon:Ribbon tag, you can specify the controls for the Quick Access Toolbar. As you can see in this example, you can use any ribbon controls on the QAT, for example RibbonButton, RibbonSplitButton, RibbonToggleButton, RibbonDropDownButton etc.

<ribbon:Ribbon.QuickAccessToolBar>
  <ribbon:RibbonQuickAccessToolBar>
    <ribbon:RibbonButton Command="{StaticResource QATCommand1}"
       ribbon:RibbonQuickAccessToolBar.Placement="InCustomizeMenuAndToolBar"/>
    <ribbon:RibbonSplitButton Command="{StaticResource QATCommand2}"
       ribbon:RibbonQuickAccessToolBar.Placement="InCustomizeMenuAndToolBar"/>
    <ribbon:RibbonToggleButton Command="{StaticResource QATCommand3}"
       ribbon:RibbonQuickAccessToolBar.Placement="InCustomizeMenu"/>
    <ribbon:RibbonDropDownButton Command="{StaticResource QATCommand4}"
       ribbon:RibbonQuickAccessToolBar.Placement="InToolBar"/>
  </ribbon:RibbonQuickAccessToolBar>
</ribbon:Ribbon.QuickAccessToolBar>

Of course, commands must also be defined for each control

<ribbon:RibbonCommand x:Key="QATCommand1" x:Name="QATCommand1"
 Executed="QATCommand_Executed"
 LabelTitle="QAT 1 - Palms"
 SmallImageSource="images/QAT1.png"
 />

 <ribbon:RibbonCommand x:Key="QATCommand2" x:Name="QATCommand2"
 Executed="QATCommand_Executed"
 LabelTitle="QAT 2 - Wizard"
 SmallImageSource="images/QAT2.png"
 />

 <ribbon:RibbonCommand x:Key="QATCommand3" x:Name="QATCommand3"
 Executed="QATCommand_Executed"
 LabelTitle="QAT 3 - Money"
 SmallImageSource="images/QAT3.png"
 />

 <ribbon:RibbonCommand x:Key="QATCommand4" x:Name="QATCommand4"
 Executed="QATCommand_Executed"
 LabelTitle="QAT 4 - Present"
 SmallImageSource="images/QAT4.png"
 />

Moreover, you can specify for each control in QAT where it should be placed:

  • InToolBar – the control will be displayed only in the ToolBar; it cannot be removed from the toolbar
  • InCustomizeMenu – the control will be available in the CustomizeMenu but it will not be displayed in the ToolBar when the application starts. If the user wants, he can check the corresponding option in the CustomizeMenu and the control will appear on the ToolBar as well.
  • InCustomizeMenuAndToolBar – the control will be displayed in the ToolBar and the CustomizeMenu as well, from the begining of the application. The user can chose to remove it from the ToolBar, by unchecking the corresponding option in the CustomizeMenu

I hope that this first part of the tutorial helped you better understand how you can add the ribbon and customize the application menu. On my next tutorial, I will focus on creating tabs, groups and adding controls on the ribbon.

Step 11: Removing the titlebar

There is just a small change we need to make in order to have a ribbon-like application: get rid of the Windows Forms specific title bar. In order to do this, first of all we have to replace the <Window> tag in the main window XAML with <ribbon:RibbonWindow> and also in code-behind, we have to derive the Window1 class from RibbonWindow, instead of Window.

Also, if you want to set a title for the application, you will have to add it in the <ribbon:Ribbon> tag, like this:

<ribbon:RibbonWindow x:Class="WPFRibbonExample.Window1"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:ribbon="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary">

<!-- resources  -->

<Grid>
<ribbon:Ribbon Title="WPF Ribbon Example">

<!-- ribbon elements  -->

</ribbon:Ribbon>
</Grid>
</ribbon:RibbonWindow>

Now, the application should look like this:

Source Code

You can download the archive with the source code from here.

Other interesting tutorials:

Posted in WPF Ribbon and tagged as , ,

8 comments on “WPF Ribbon (CTP) – Part 1 – Add Ribbon and Customize

Leave a Reply to yvisek Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.