Back to Devexpress

How to create a RibbonControl

wpf-8178-controls-and-libraries-ribbon-bars-and-menu-ribbon-examples-how-to-create-a-ribboncontrol.md

latest33.9 KB
Original Source

How to create a RibbonControl

  • Aug 01, 2019
  • 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:

View Example

xaml
<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>
csharp
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;
            }
        }
    }
}
vb
Imports DevExpress.Xpf.Bars
Imports DevExpress.Xpf.Core
Imports DevExpress.Xpf.Editors.Settings
Imports DevExpress.Xpf.Ribbon
Imports System
Imports System.Collections.ObjectModel
Imports System.Globalization
Imports System.Windows
Imports System.Windows.Documents
Imports System.Windows.Media
Imports System.Windows.Media.Imaging
Imports System.Windows.Threading

Namespace RibbonControl_Ex
    Public Partial Class MainWindow
        Inherits ThemedWindow

        Public Sub New()
            InitializeComponent()
            bFileName.Content = "Document 1"
            CType(eFontSize.EditSettings, ComboBoxEditSettings).ItemsSource =(New FontSizes()).Items
            InitializeFontFamilyGallery()
        End Sub

        Private Sub InitializeFontFamilyGallery()
            For Each fontFamily As FontFamily In(New DecimatedFontFamilies()).Items
                Dim src As ImageSource = CreateImage(fontFamily)
                FontFamilyGalleryGroup.Items.Add(CreateItem(fontFamily, src))
                FontFamilyDropDownGalleryGroup.Items.Add(CreateItem(fontFamily, src))
            Next
        End Sub

        Private fmtText As FormattedText = Nothing

        Private Function createFormattedText(ByVal fontFamily As FontFamily) As FormattedText
            Return New FormattedText("Aa", CultureInfo.CurrentCulture, FlowDirection.LeftToRight, New Typeface(fontFamily, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal), 18, Brushes.Black, Nothing, TextFormattingMode.Ideal)
        End Function

        Private Function CreateImage(ByVal fontFamily As FontFamily) As ImageSource
            Const DimensionSize As Double = 32
            Const HalfDimensionSize As Double = DimensionSize / 2R
            Dim v As DrawingVisual = New DrawingVisual()
            Dim c As DrawingContext = v.RenderOpen()
            c.DrawRectangle(Brushes.White, Nothing, New Rect(0, 0, DimensionSize, DimensionSize))
            If fmtText Is Nothing Then fmtText = createFormattedText(fontFamily)
            fmtText.SetFontFamily(fontFamily)
            fmtText.TextAlignment = TextAlignment.Center
            Dim verticalOffset As Double =(DimensionSize - fmtText.Baseline) / 2R
            c.DrawText(fmtText, New Point(HalfDimensionSize, verticalOffset))
            c.Close()
            Dim rtb As RenderTargetBitmap = New RenderTargetBitmap(CInt(DimensionSize), CInt(DimensionSize), 96, 96, PixelFormats.Pbgra32)
            rtb.Render(v)
            Return rtb
        End Function

        Private Function CreateItem(ByVal fontFamily As FontFamily, ByVal image As ImageSource) As GalleryItem
            Dim item As GalleryItem = New GalleryItem()
            item.Glyph = image
            item.Caption = fontFamily.ToString()
            item.Tag = fontFamily
            Return item
        End Function

        Private Sub textEditor_SelectionChanged(ByVal sender As Object, ByVal e As RoutedEventArgs)
            ShowHideSelectionCategory()
            UpdateStatusCaretPosition()
            InvokeUpdateFormat()
        End Sub

        Private isInvokePending As Boolean = False

        Private Sub InvokeUpdateFormat()
            If Not isInvokePending Then
                Dispatcher.BeginInvoke(DispatcherPriority.Background, New Action(AddressOf UpdateFormat))
                isInvokePending = True
            End If

            UpdateFormat()
        End Sub

        Protected Sub UpdateFormat()
            Dim value As Object = textEditor.Selection.GetPropertyValue(TextElement.FontSizeProperty)
            eFontSize.EditValue = If(value Is DependencyProperty.UnsetValue, Nothing, value)
        End Sub

        Private Sub ShowHideSelectionCategory()
            If textEditor Is Nothing Then
                categorySelection.IsVisible = False
            Else
                categorySelection.IsVisible = Not SelectedTextIsNullOrEmpty
            End If

            If categorySelection.IsVisible Then RibbonControl.SelectedPage = categorySelection.Pages(0)
        End Sub

        Public ReadOnly Property SelectedTextIsNullOrEmpty As Boolean
            Get
                Return String.IsNullOrEmpty(textEditor.Selection.Text)
            End Get
        End Property

        Private Sub UpdateStatusCaretPosition()
            Dim line As Integer = 0
            textEditor.CaretPosition.GetLineStartPosition(-100000, line)
            Dim col As Integer = textEditor.CaretPosition.GetOffsetToPosition(textEditor.CaretPosition.GetLineStartPosition(0))
            bPosInfo.Content = "Line: " & (-line).ToString() & " Position: " & (-col).ToString()
        End Sub

        Private Sub FontFamilyGallery_ItemChecked(ByVal sender As Object, ByVal e As GalleryItemEventArgs)
            Dim newFontFamily As FontFamily = CType(e.Item.Tag, FontFamily)
            ApplyPropertyValueToSelectedText(TextElement.FontFamilyProperty, newFontFamily)
        End Sub

        Private Sub eFontSize_EditValueChanged(ByVal sender As Object, ByVal e As RoutedEventArgs)
            ApplyPropertyValueToSelectedText(TextElement.FontSizeProperty, eFontSize.EditValue)
        End Sub

        Private Sub ApplyPropertyValueToSelectedText(ByVal formattingProperty As DependencyProperty, ByVal value As Object)
            If value Is Nothing Then Return
            textEditor.Selection.ApplyPropertyValue(formattingProperty, value)
        'InvokeUpdateFormat();
        'InvokeFocusEdit();
        End Sub

        Private Sub OptionsButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            Call TryCast(RibbonControl.ApplicationMenu, ApplicationMenu).ClosePopup()
        End Sub

        Private Sub ExitButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            Call TryCast(RibbonControl.ApplicationMenu, ApplicationMenu).ClosePopup()
        End Sub

        Private Sub groupEdit_CaptionButtonClick(ByVal sender As Object, ByVal e As EventArgs)
            MessageBox.Show("DevExpress Ribbon Control", "Edit Settings Dialog")
        End Sub

        Private Sub bAbout_ItemClick(ByVal sender As Object, ByVal e As ItemClickEventArgs)
            MessageBox.Show("DevExpress Ribbon Control", "About Window")
        End Sub

        Private Sub groupFile_CaptionButtonClick(ByVal sender As Object, ByVal e As RibbonCaptionButtonClickEventArgs)
            MessageBox.Show("DevExpress Ribbon Control", "File Settings Dialog")
        End Sub
    End Class

    Public Class RecentItem

        Public Property Number As Integer

        Public Property FileName As String
    End Class

    Public Class ButtonWithImageContent

        Public Property ImageSource As String

        Public Property Content As Object
    End Class

    Public Class FontSizes

        Public ReadOnly Property Items As Double()
            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}
            End Get
        End Property
    End Class

    Public Class DecimatedFontFamilies
        Inherits FontFamilies

        Const DecimationFactor As Integer = 5

        Public Overrides ReadOnly Property Items As ObservableCollection(Of FontFamily)
            Get
                Dim res As ObservableCollection(Of FontFamily) = New ObservableCollection(Of FontFamily)()
                For i As Integer = 0 To ItemsCore.Count - 1
                    If i Mod DecimationFactor = 0 Then res.Add(ItemsCore(i))
                Next

                Return res
            End Get
        End Property
    End Class

    Public Class FontFamilies

        Private Shared itemsField As ObservableCollection(Of FontFamily)

        Protected Shared ReadOnly Property ItemsCore As ObservableCollection(Of FontFamily)
            Get
                If itemsField Is Nothing Then
                    itemsField = New ObservableCollection(Of FontFamily)()
                    For Each fam As FontFamily In Fonts.SystemFontFamilies
                        If Not IsValidFamily(fam) Then Continue For
                        itemsField.Add(fam)
                    Next
                End If

                Return itemsField
            End Get
        End Property

        Public Shared Function IsValidFamily(ByVal fam As FontFamily) As Boolean
            For Each f As Typeface In fam.GetTypefaces()
                Dim g As GlyphTypeface = Nothing
                Try
                    If f.TryGetGlyphTypeface(g) Then
                        If g.Symbol Then Return False
                    End If
                Catch __unusedException1__ As Exception
                    Return False
                End Try
            Next

            Return True
        End Function

        Public Overridable ReadOnly Property Items As ObservableCollection(Of FontFamily)
            Get
                Dim res As ObservableCollection(Of FontFamily) = New ObservableCollection(Of FontFamily)()
                For Each fm As FontFamily In ItemsCore
                    res.Add(fm)
                Next

                Return res
            End Get
        End Property
    End Class
End Namespace