Skip to main content

DevExpress v24.2 Update — Your Feedback Matters

Our What's New in v24.2 webpage includes product-specific surveys. Your response to our survey questions will help us measure product satisfaction for features released in this major update and help us refine our plans for our next major release.

Take the survey Not interested

How to create a RibbonControl

  • 10 minutes to read

This example shows how to create a RibbonControl in XAML. The control contains a Default Page Category, displaying three Ribbon pages (File, Edit and Format). In addition, a custom page category (“Selection”) is defined, which is initially hidden, and made visible on selecting text in a text editor (see the complete sample).

The following image shows the result:

RibbonControl_Ex

View Example

<dx:ThemedWindow x:Class="RibbonControl_Ex.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="379" Width="643"
        xmlns:local="clr-namespace:RibbonControl_Ex"
        xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
        xmlns:dxb="http://schemas.devexpress.com/winfx/2008/xaml/bars"
        xmlns:dxr="http://schemas.devexpress.com/winfx/2008/xaml/ribbon"
        xmlns:dxc="http://schemas.devexpress.com/winfx/2008/xaml/core"
        xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"
        Icon="{dxc:DXImage Image=Home_16x16.png}">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <dxr:RibbonControl x:Name="RibbonControl" Grid.Row="0" 
                           ApplicationButtonSmallIcon="{dxc:DXImage Image=Home_16x16.png}" 
                           ApplicationButtonLargeIcon="{dxc:DXImage Image=Home_32x32.png}" 
                           ApplicationButtonText="File" 
                           PageCategoryAlignment="Right"
                           RibbonStyle="Office2010">
            <!--region #AppMenu-->
            <dxr:RibbonControl.ApplicationMenu>
                <dxr:ApplicationMenu RightPaneWidth="280" ShowRightPane="True">
                    <dxr:ApplicationMenu.ItemLinks>
                        <dxb:BarButtonItemLink BarItemName="bNew"/>
                        <dxb:BarButtonItemLink BarItemName="bOpen"/>
                        <dxb:BarItemLinkSeparator/>
                        <dxb:BarSplitButtonItemLink BarItemName="sbSave"/>
                        <dxb:BarButtonItemLink BarItemName="bPrint"/>
                        <dxb:BarItemLinkSeparator/>
                        <dxb:BarButtonItemLink BarItemName="bAbout"/>
                    </dxr:ApplicationMenu.ItemLinks>
                    <dxr:ApplicationMenu.RightPane>
                        <Border Background="White" BorderThickness="1,0,0,0" BorderBrush="LightGray">
                            <Grid>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition Height="*"/>
                                </Grid.RowDefinitions>
                                <Border BorderThickness="0,0,0,1" BorderBrush="LightGray" Margin="7,5,5,0">
                                    <Label FontWeight="Bold">Recent Documents:</Label>
                                </Border>
                                <ListBox Grid.Row="1" BorderThickness="0" Margin="2,0,0,0" >
                                    <ListBox.ItemTemplate>
                                        <DataTemplate>
                                            <StackPanel Orientation="Horizontal" Margin="0,2,0,0">
                                                <Border BorderThickness="0,0,0,1" BorderBrush="Black">
                                                    <TextBlock Text="{Binding Number}"/>
                                                </Border>
                                                <TextBlock Text="{Binding FileName}" Margin="7,0,0,0"/>
                                            </StackPanel>
                                        </DataTemplate>
                                    </ListBox.ItemTemplate>
                                    <ListBox.Items>
                                        <local:RecentItem  Number="1" FileName="Document4.rtf"/>
                                        <local:RecentItem  Number="2" FileName="Document3.rtf"/>
                                        <local:RecentItem  Number="3" FileName="Document2.rtf"/>
                                        <local:RecentItem  Number="4" FileName="Document1.rtf"/>
                                    </ListBox.Items>
                                </ListBox>
                            </Grid>
                        </Border>
                    </dxr:ApplicationMenu.RightPane>
                    <dxr:ApplicationMenu.BottomPane>
                        <StackPanel Orientation="Horizontal">
                            <Button Click="OptionsButton_Click" Content="Options" Width="100" Margin="0,0,10,0" />
                            <Button Click="ExitButton_Click" Content="Exit" Width="100" />
                        </StackPanel>
                    </dxr:ApplicationMenu.BottomPane>
                </dxr:ApplicationMenu>
            </dxr:RibbonControl.ApplicationMenu>
            <!--endregion #AppMenu-->

            <!--region #PageHeaderItemLinks-->
            <dxr:RibbonControl.PageHeaderItems>
                <dxb:BarEditItem x:Name="eRibbonStyle" Content="Ribbon Style:" 
                    EditWidth="100" 
                    ClosePopupOnChangingEditValue="True" 
                    EditValue="{Binding RibbonStyle, ElementName=RibbonControl}">
                    <dxb:BarEditItem.EditSettings>
                        <dxe:ComboBoxEditSettings IsTextEditable="False" PopupMaxHeight="250" 
                                                  ItemsSource="{dxe:EnumItemsSource EnumType={x:Type dxr:RibbonStyle}}"/>
                    </dxb:BarEditItem.EditSettings>
                </dxb:BarEditItem>
                <dxb:BarButtonItem Name="bAbout" Content="About" 
                                   Glyph="{dxc:DXImage Image=Info_16x16.png}" 
                                   LargeGlyph="{dxc:DXImage Image=Info_32x32.png}" 
                                   ItemClick="bAbout_ItemClick" />
            </dxr:RibbonControl.PageHeaderItems>
            <!--endregion #PageHeaderItemLinks-->

            <!--region #ToolbarItemLinks-->
            <dxr:RibbonControl.ToolbarItemLinks>
                <dxb:BarButtonItemLink BarItemName="bOpen"/>
                <dxb:BarButtonItemLink BarItemName="bSave"/>
            </dxr:RibbonControl.ToolbarItemLinks>
            <!--endregion #ToolbarItemLinks-->

            <!--region #DefaultPageCategory-->
            <dxr:RibbonDefaultPageCategory>
                <dxr:RibbonPage Caption="Home">
                    <dxr:RibbonPageGroup Name="pgFile" Caption="File" 
                                         ShowCaptionButton="True"
                                         CaptionButtonClick="groupFile_CaptionButtonClick">
                        <dxb:BarButtonItem Name="bNew" Content="New" 
                               Glyph="{dxc:DXImage Image=New_16x16.png}" 
                               LargeGlyph="{dxc:DXImage Image=New_32x32.png}"  
                               Description="Creates a new document."
                               Hint="Creates a blank document."
                               RibbonStyle="Large"/>

                        <dxb:BarButtonItem Name="bOpen" Content="Open" 
                               Glyph="{dxc:DXImage Image=Open_16x16.png}" 
                               LargeGlyph="{dxc:DXImage Image=Open_32x32.png}" 
                               Description="Opens a file."
                               Hint="Opens a file."
                               RibbonStyle="SmallWithText"/>

                        <dxb:BarButtonItem Name="bClose" Content="Close" 
                               Glyph="{dxc:DXImage Image=Close_16x16.png}" 
                               LargeGlyph="{dxc:DXImage Image=Close_32x32.png}"
                               Hint="Closes the current document"
                               RibbonStyle="SmallWithText"/>

                        <dxb:BarButtonItem Name="bPrint" Content="Print" 
                               Glyph="{dxc:DXImage Image=Print_16x16.png}" 
                               LargeGlyph="{dxc:DXImage Image=Print_32x32.png}"  
                               Description="Prints the document."
                               Hint="Prints the document." 
                               RibbonStyle="SmallWithText"/>

                        <dxb:BarItemLinkSeparator/>

                        <dxb:BarSplitButtonItem Name="sbSave" Content="Save" 
                                    Glyph="{dxc:DXImage Image=Save_16x16.png}" 
                                    LargeGlyph="{dxc:DXImage Image=Save_32x32.png}" 
                                    RibbonStyle="Large">
                            <dxb:BarSplitButtonItem.PopupControl >
                                <dxb:PopupMenu>
                                    <dxb:BarButtonItem Name="bSave" Content="Save" 
                                        Glyph="{dxc:DXImage Image=Save_16x16.png}" 
                                        LargeGlyph="{dxc:DXImage Image=Save_32x32.png}"  
                                        Description="Saves the document."
                                        Hint="Saves the document."/>
                                    <dxb:BarButtonItem Name="bSaveAs" Content="Save As..." 
                                        Glyph="{dxc:DXImage Image=SaveDialog_16x16.png}" 
                                        LargeGlyph="{dxc:DXImage Image=SaveDialog_32x32.png}" 
                                        Description="Save Document As..."
                                        Hint="Save Document As..."/>
                                </dxb:PopupMenu>
                            </dxb:BarSplitButtonItem.PopupControl>
                        </dxb:BarSplitButtonItem>
                    </dxr:RibbonPageGroup>

                    <dxr:RibbonPageGroup Caption="Edit" ShowCaptionButton="True" CaptionButtonClick="groupEdit_CaptionButtonClick">
                        <dxb:BarButtonItem Name="bPaste" Content="Paste" 
                               Glyph="{dxc:DXImage Image=Paste_16x16.png}" 
                               LargeGlyph="{dxc:DXImage Image=Paste_32x32.png}" RibbonStyle="Large"/>
                        <dxb:BarButtonItem Name="bCut" Content="Cut" 
                               Glyph="{dxc:DXImage Image=Cut_16x16.png}"  RibbonStyle="SmallWithText"/>
                        <dxb:BarButtonItem Name="bCopy" Content="Copy" 
                               Glyph="{dxc:DXImage Image=Copy_16x16.png}"  RibbonStyle="SmallWithText"/>
                        <dxb:BarButtonItem Name="bClear" Content="Clear" 
                               Glyph="{dxc:DXImage Image=Delete_16x16.png}"  RibbonStyle="SmallWithText"/>
                    </dxr:RibbonPageGroup>

                    <dxr:RibbonPageGroup Caption="Format" ShowCaptionButton="False">
                        <!--region #BarButtonGroup-->
                        <dxr:BarButtonGroup Name="bgFontShape" RibbonStyle="SmallWithoutText">
                            <dxb:BarCheckItem Name="bBold" Content="Bold" 
                              Glyph="{dxc:DXImage Image=Bold_16x16.png}" />
                            <dxb:BarCheckItem Name="bItalic" Content="Italic" 
                              Glyph="{dxc:DXImage Image=Italic_16x16.png}" />
                            <dxb:BarCheckItem Name="bUnderline" Content="Underline" 
                              Glyph="{dxc:DXImage Image=Underline_16x16.png}" />
                        </dxr:BarButtonGroup>
                        <!--endregion #BarButtonGroup-->
                    </dxr:RibbonPageGroup>
                </dxr:RibbonPage>
            </dxr:RibbonDefaultPageCategory>
            <!--endregion #DefaultPageCategory-->

            <!--region #CustomPageCategory-->
            <dxr:RibbonPageCategory x:Name="categorySelection" 
                                    Caption="Selection" 
                                    Color="Yellow" 
                                    IsVisible="False">
                <dxr:RibbonPage Caption="Gallery Page">
                    <dxr:RibbonPageGroup Caption="Font" ShowCaptionButton="False">
                        <!--region #RibbonGalleryBarItem-->
                        <dxr:RibbonGalleryBarItem Name="gFont" Glyph="{dxc:DXImage Image=ChangeFontStyle_16x16.png}" Content="Font">
                            <dxr:RibbonGalleryBarItem.Links>
                                <dxb:BarEditItemLink BarItemName="eFontSize" RibbonStyle="SmallWithText"/>
                            </dxr:RibbonGalleryBarItem.Links>
                            <dxr:RibbonGalleryBarItem.Gallery>
                                <dxb:Gallery MinColCount="1" ColCount="5" 
                                    ItemCheckMode="Single" 
                                    IsGroupCaptionVisible="False" 
                                    IsItemCaptionVisible="False"
                                    IsItemDescriptionVisible="False" 
                                    ItemChecked="FontFamilyGallery_ItemChecked" 
                                    ItemCaptionVerticalAlignment="Center">
                                    <dxb:Gallery.Groups>
                                        <dxb:GalleryItemGroup Name="FontFamilyGalleryGroup" />
                                    </dxb:Gallery.Groups>
                                </dxb:Gallery>
                            </dxr:RibbonGalleryBarItem.Gallery>

                            <dxr:RibbonGalleryBarItem.DropDownGallery>
                                <dxb:Gallery MinColCount="1" ColCount="1" 
                                    RowCount="5" 
                                    ItemCheckMode="Single" 
                                    IsGroupCaptionVisible="False"
                                    AllowFilter="False"
                                    IsItemGlyphVisible="True" 
                                    IsItemDescriptionVisible="False" 
                                    ItemContentHorizontalAlignment="Stretch"
                                    ItemContentVerticalAlignment="Center" 
                                    ItemChecked="FontFamilyGallery_ItemChecked"
                                    SizeMode="Vertical">
                                    <dxb:Gallery.Groups>
                                        <dxb:GalleryItemGroup Name="FontFamilyDropDownGalleryGroup" />
                                    </dxb:Gallery.Groups>
                                </dxb:Gallery>
                            </dxr:RibbonGalleryBarItem.DropDownGallery>
                        </dxr:RibbonGalleryBarItem>
                        <!--endregion #RibbonGalleryBarItem-->

                        <dxb:BarEditItem Name="eFontSize" RibbonStyle="SmallWithoutText" EditWidth="90"
                             Content="Font Size:" 
                             EditValueChanged="eFontSize_EditValueChanged">
                            <dxb:BarEditItem.EditSettings>
                                <dxe:ComboBoxEditSettings PopupMaxHeight="250" IsTextEditable="False"/>
                            </dxb:BarEditItem.EditSettings>
                        </dxb:BarEditItem>

                    </dxr:RibbonPageGroup>
                </dxr:RibbonPage>
            </dxr:RibbonPageCategory>
            <!--endregion #CustomPageCategory-->
        </dxr:RibbonControl>

        <!--region #RibbonStatusBarControl-->
        <dxr:RibbonStatusBarControl Grid.Row="2" Name="StatusBar" IsSizeGripVisible="True" Grid.ColumnSpan="2">
            <dxr:RibbonStatusBarControl.RightItems>
                <dxb:BarStaticItem Name="bFileName" ItemMinWidth="150" AutoSizeMode="Fill" Content="Binding"/>
            </dxr:RibbonStatusBarControl.RightItems>
            <dxr:RibbonStatusBarControl.LeftItems>
                <dxb:BarStaticItem Name="bPosInfo" ItemMinWidth="150"/>
            </dxr:RibbonStatusBarControl.LeftItems>
        </dxr:RibbonStatusBarControl>
        <!--endregion #RibbonStatusBarControl-->

        <RichTextBox x:Name="textEditor" Grid.Row="1" BorderThickness="0" SelectionChanged="textEditor_SelectionChanged" Grid.ColumnSpan="2"/>

    </Grid>
</dx:ThemedWindow>
using DevExpress.Xpf.Bars;
using DevExpress.Xpf.Core;
using DevExpress.Xpf.Editors.Settings;
using DevExpress.Xpf.Ribbon;
using System;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;

namespace RibbonControl_Ex {
    public partial class MainWindow : ThemedWindow {

        public MainWindow() {
            InitializeComponent();
            bFileName.Content = "Document 1";
            ((ComboBoxEditSettings)eFontSize.EditSettings).ItemsSource = (new FontSizes()).Items;
            InitializeFontFamilyGallery();
        }

        void InitializeFontFamilyGallery() {
            foreach (FontFamily fontFamily in (new DecimatedFontFamilies()).Items) {
                ImageSource src = CreateImage(fontFamily);
                FontFamilyGalleryGroup.Items.Add(CreateItem(fontFamily, src));
                FontFamilyDropDownGalleryGroup.Items.Add(CreateItem(fontFamily, src));
            }
        }

        FormattedText fmtText = null;
        FormattedText createFormattedText(FontFamily fontFamily) {
            return new FormattedText("Aa", CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(fontFamily, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal), 18, Brushes.Black, null, TextFormattingMode.Ideal);
        }

        ImageSource CreateImage(FontFamily fontFamily) {
            const double DimensionSize = 32;
            const double HalfDimensionSize = DimensionSize / 2d;
            DrawingVisual v = new DrawingVisual();
            DrawingContext c = v.RenderOpen();
            c.DrawRectangle(Brushes.White, null, new Rect(0, 0, DimensionSize, DimensionSize));
            if (fmtText == null)
                fmtText = createFormattedText(fontFamily);
            fmtText.SetFontFamily(fontFamily);
            fmtText.TextAlignment = TextAlignment.Center;
            double verticalOffset = (DimensionSize - fmtText.Baseline) / 2d;
            c.DrawText(fmtText, new Point(HalfDimensionSize, verticalOffset));
            c.Close();

            RenderTargetBitmap rtb = new RenderTargetBitmap((int)DimensionSize, (int)DimensionSize, 96, 96, PixelFormats.Pbgra32);
            rtb.Render(v);
            return rtb;
        }

        GalleryItem CreateItem(FontFamily fontFamily, ImageSource image) {
            GalleryItem item = new GalleryItem();
            item.Glyph = image;
            item.Caption = fontFamily.ToString();
            item.Tag = fontFamily;
            return item;
        }

        void textEditor_SelectionChanged(object sender, RoutedEventArgs e) {
            ShowHideSelectionCategory();
            UpdateStatusCaretPosition();
            InvokeUpdateFormat();
        }

        bool isInvokePending = false;

        void InvokeUpdateFormat() {
            if (!isInvokePending) {
                Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(UpdateFormat));
                isInvokePending = true;
            }
            UpdateFormat();
        }

        protected void UpdateFormat() {
            object value = textEditor.Selection.GetPropertyValue(TextElement.FontSizeProperty);
            eFontSize.EditValue = (value == DependencyProperty.UnsetValue) ? null : value;
        }

        void ShowHideSelectionCategory() {
            if (textEditor == null)
                categorySelection.IsVisible = false;
            else
                categorySelection.IsVisible = !SelectedTextIsNullOrEmpty;
            if (categorySelection.IsVisible)
                RibbonControl.SelectedPage = categorySelection.Pages[0];
        }

        public bool SelectedTextIsNullOrEmpty { get { return string.IsNullOrEmpty(textEditor.Selection.Text); } }

        void UpdateStatusCaretPosition() {
            int line = 0;
            textEditor.CaretPosition.GetLineStartPosition(-100000, out line);
            int col = textEditor.CaretPosition.GetOffsetToPosition(textEditor.CaretPosition.GetLineStartPosition(0));
            bPosInfo.Content = "Line: " + (-line).ToString() + "  Position: " + (-col).ToString();
        }

        void FontFamilyGallery_ItemChecked(object sender, GalleryItemEventArgs e) {
            FontFamily newFontFamily = (FontFamily)e.Item.Tag;
            ApplyPropertyValueToSelectedText(TextElement.FontFamilyProperty, newFontFamily);
        }

        void eFontSize_EditValueChanged(object sender, RoutedEventArgs e) {
            ApplyPropertyValueToSelectedText(TextElement.FontSizeProperty, eFontSize.EditValue);
        }

        void ApplyPropertyValueToSelectedText(DependencyProperty formattingProperty, object value) {
            if (value == null) return;
            textEditor.Selection.ApplyPropertyValue(formattingProperty, value);
            //InvokeUpdateFormat();
            //InvokeFocusEdit();
        }

        void OptionsButton_Click(object sender, RoutedEventArgs e) {
            (RibbonControl.ApplicationMenu as ApplicationMenu).ClosePopup();
        }
        void ExitButton_Click(object sender, RoutedEventArgs e) {
            (RibbonControl.ApplicationMenu as ApplicationMenu).ClosePopup();
        }

        void groupEdit_CaptionButtonClick(object sender, EventArgs e) {
            MessageBox.Show("DevExpress Ribbon Control", "Edit Settings Dialog");
        }

        private void bAbout_ItemClick(object sender, ItemClickEventArgs e) {
            MessageBox.Show("DevExpress Ribbon Control", "About Window");
        }

        private void groupFile_CaptionButtonClick(object sender, RibbonCaptionButtonClickEventArgs e) {
            MessageBox.Show("DevExpress Ribbon Control", "File Settings Dialog");

        }
    }

    public class RecentItem {
        public int Number { get; set; }
        public string FileName { get; set; }
    }

    public class ButtonWithImageContent {
        public string ImageSource { get; set; }
        public object Content { get; set; }
    }

    public class FontSizes {
        public double[] Items {
            get {
                return new double[] {
                    3.0, 4.0, 5.0, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5,
                    10.0, 10.5, 11.0, 11.5, 12.0, 12.5, 13.0, 13.5, 14.0, 15.0,
                    16.0, 17.0, 18.0, 19.0, 20.0, 22.0, 24.0, 26.0, 28.0, 30.0,
                    32.0, 34.0, 36.0, 38.0, 40.0, 44.0, 48.0, 52.0, 56.0, 60.0, 64.0, 68.0, 72.0, 76.0,
                    80.0, 88.0, 96.0, 104.0, 112.0, 120.0, 128.0, 136.0, 144.0
                };
            }
        }
    }

    public class DecimatedFontFamilies : FontFamilies {
        const int DecimationFactor = 5;
        public override ObservableCollection<FontFamily> Items {
            get {
                ObservableCollection<FontFamily> res = new ObservableCollection<FontFamily>();
                for (int i = 0; i < ItemsCore.Count; i++) {
                    if (i % DecimationFactor == 0)
                        res.Add(ItemsCore[i]);
                }
                return res;
            }
        }
    }

    public class FontFamilies {
        static ObservableCollection<FontFamily> items;
        protected static ObservableCollection<FontFamily> ItemsCore {
            get {
                if (items == null) {
                    items = new ObservableCollection<FontFamily>();
                    foreach (FontFamily fam in Fonts.SystemFontFamilies) {
                        if (!IsValidFamily(fam)) continue;
                        items.Add(fam);
                    }
                }
                return items;
            }
        }

        public static bool IsValidFamily(FontFamily fam) {
            foreach (Typeface f in fam.GetTypefaces()) {
                GlyphTypeface g = null;
                try {
                    if (f.TryGetGlyphTypeface(out g))
                        if (g.Symbol) return false;
                } catch (Exception) {
                    return false;
                }
            }
            return true;
        }

        public virtual ObservableCollection<FontFamily> Items {
            get {
                ObservableCollection<FontFamily> res = new ObservableCollection<FontFamily>();
                foreach (FontFamily fm in ItemsCore) {
                    res.Add(fm);
                }
                return res;
            }
        }
    }
}