Creating a mobile application

To create a mobile application that uses MobileRibbon, begin with a basic WPF application and add a reference to DevComponents.WPF.Mobile. To work properly, MobileRibbon needs to live inside a MobileWindow, so you will want to change the base class of MainWindow to MobileWindow. Once you have a MobileWindow, the next step is to set the MobileTheme. The chosen MobileTheme sets the primary color of the ribbon (blue, green, orange or purple.) Additionally, it defines a set of global resources used throughout the mobile namespace. The attached dependency property MobileTheme.ApplicationTheme sets the theme, which can be one of the built-in themes or a custom theme that you have defined. Here is an example, which would be put in the main attributes section of the MobileWindow’s xaml.

mobile:MobileTheme.ApplicationTheme="{x:Static mobile:MobileTheme.BlueTheme}"

Notable properties of MobileWindow are:

  • ChromeStyle – Determines the look of the window’s chrome. Possible values are None, Default (standard Windows 10 desktop chrome,) Windows10, Office2013 and ExtendedRibbon (the chrome extends into the ribbon and is the same color.)
  • ShowFullScreenButton – Determines whether the chrome has a button which puts the window into full screen mode.
  • ChromeToolBarItems – used for adding custom toolbar items to the chrome in xaml or code behind. (Use ChromeToolBarItemsSourcee for data binding scenarios.)

Adding a settings flyout

Let’s look at adding a SettingsFlyout to the window before digging into the ribbon. Although the flyout is normally opened via a “Settings” button located in the ribbon’s backstage, the SettingsFlyout control itself is not located inside the ribbon. Instead, it’s a child of the window. SettingsFlyout should be added to the root grid of the window in such way that, when opened, it is able to span the window’s full height and width. For example, if the root grid has 2 rows an 2 columns, the flyout should have both Grid.RowSpan and Grid.ColumnSpan set to 2.

After adding the flyout, you can set its Header and Footer properties. Both are displayed in the main view, when no item is selected, along with the list of the items.

SettingsFlyout is a container for SettingsFlyoutItem controls. A SettingsFlyoutItem has both Content and Header properties. Headers of all items are listed in the flyout’s main view, which is displayed when no item is selected. Both Header and Content are displayed when an item is selected.

SettingsFlyoutItem does not require Content to be useful. In this case, you can set a Command (and optionally a CommandParameter) or you can handle the items’s Clicked event and do what ever is required. If you want the flyout to be closed when an item is clicked, set ClosesFlyout to true. You can also set IsSelectable to false if you need the flyout to stay open but don’t want the item to be selected.

Adding the ribbon

MobileRibbon should be inserted into the first row of the window’s root grid and allowed to span across all columns.

MobileRibbon can display a Title which is not the same as the window’s title. TitleTemplate shows how to render Title. If you have set a value for Title but want to hide it, use the HideTitle property.

The ribbon has an internal toolbar where you can place buttons and other controls that are separate from main display – off to the right of the item headers. To put objects into the toolbar in xaml or code behind, use the ToolBarItems property. For data binding scenarios, place the objects into a collection which is bound to the ToolBarItemsSource property. Here is an example in xaml:

<mobile:Ribbon>     
<mobile:Ribbon.ToolBarItems>        
<Button controls:ControlBehavior.ImageSource="Images/smiley.png" Click="FeedBackButton_Click" />        
<Button controls:ControlBehavior.ImageSource="Images/question.png" Click="QuestionButton_Click" />                    
</mobile:Ribbon.ToolBarItems>
</mobile:Ribbon>

The ribbon can be collapsed. When collapsed the bottom strip containing the selected ribbon item’s contents is hidden. The ribbon can be collapsed and expanded manually via the IsCollapsed property. The ribbon can also be set up to collapse automatically via the AutoCollapseOption property.  AutoCollapseOption is an enumeration with possible values of None and WhenSelectedRibbonItemClicked. If set to the latter, then, as the name suggests, the ribbon will be collapsed automatically when the user clicks on a ribbon item that is already selected. WhenSelectedRibbonItemClicked is the default value for AutoCollapseOption.

Setting up a backstage will be covered in the next section. But the ribbon itself has properties that are related to the backstage, which are gone over here. By default, if you set up a backstage then the button used to open it will be shown, and if there is no backstage, the button is not shown. It is possible to override this behavior with the ShowBackstageButton property. The backstage button’s content is set via BackstageButtonContent, while BackstageButtonContentTemplate shows how to render it. If you need to know whether the backstage is open, use IsBackstageOpen.

Adding a backstage

The ribbon’s backstage is implemented by the Backstage control. To add a backstage to the ribbon, create a Backstage control and set it as the value of the ribbon’s Backstage property. Alternatively, you can bind a data object to the Backstage property and use an implied DataTemplate with a Backstage at its root.

Backstage is a container for BackStageItem controls. A BackStageItem is very similar to a SettingsFlyoutItem, described above. In fact, the only difference between the two is SettingsFlyoutItem has its ClosesFlyout property while the BackstageItem has a property named ClosesBackstage. Since they are functionally identical, they behave the same and are used in the same way.

Something worth noting with respect to the Backstage and the SettingsFlyout is that normally a button in the backstage is used to open the settings flyout. To make this possible, a RoutedCommand, named OpenSettingsFlyoutCommand, has been defined as a static property of MobileWindow. By setting this as the command of a backstage item, your user can open the settings from the backstage. For example:

<mobile:BackstageItem Header="Settings"                        
IsSelectable
="False"
                      ClosesBackstage="True" 
                     Command="{x:Static mobile:MobileWindow.OpenSettingsFlyoutCommand}"
/>

Adding items to the ribbon

MobileRibbon is a container for MobileRibbonItem controls. In Xaml, MobileRibbonItem controls can be added directly as children the Ribbon. In code behind, you would add them to the ribbon’s Items collection. In data binding scenarios, create a collection of data objects and bind it to the ribbon’s ItemsSource property.

RibbonItem’s Header property specifies the object which is displayed in the tabs section of the ribbon. Use HeaderTemplate to show how to render Header.

When the user clicks on the header of a ribbon item, its Click event is raised and its Command executed, if it has one, and it is selected. To programmatically set whether a ribbon item is selected, use its IsSelected property. When IsSelected changes, whether by user action or programmatically, the ribbon item will raise the Selected / Unselected event, as appropriate. Both events are routed events.

Adding elements to a ribbon item.

Technically speaking, UIElements of any type can be added to the RibbonItem’s Items collection and be displayed when the RibbonItem is selected. Elements can be added in Xaml as direct children. For code behind, use the Items collection and for data binding scenarios create a collection of data objects and bind it to the ItemsSource property. RibbonItem does not have an ItemTemplate property, so if you do put data objects into it, you will also need to define an implied DataTemplate targetting the data objects’ Type which shows how they should be rendered.

Even though any type of UIElement can be added to a RibbonItem, to achieve compatibility with the ribbon’s built-in styling and behavior use controls designed and implemented specifically for it. These are:

  • GroupBar – A container for grouping other elements that are related to each other. Has a button that opens a popup for showing the overflow items.
  • Gallery – A container for a collection of selectable items, of which one (or zero) can be selected at a time. Supports categories of items.
  • GalleryBar – A Gallery with a button that opens a popup for showing its items. Can display a subset of the items in the main display.
  • RibbonComboBox – A normal combo box in function, but based on Gallery in order to support categories.
  • RibbonPopupButton – An container for a collection of items, which appears as a button. When the button is pressed a popup opens to show the items.
  • RibbonButton – Exttends ButtonBase (in Windows.Controls.Primitives) with properties and functionality to support compatibility with the ribbon and make your (the programmer’s) job easier.
  • RibbonToggleButton – A toggle button derived from RibbonButton.
  • RibbonRadioButton – A radio button derived from RibbonToggleButton.
  • RibbonCheckBox – A check box derived from RibbonToggle Buttton.

Of these, the GroupBar is most often the child of a ribbon item, because it is a container for all the others (except for GalleryBar) and it supports overflowing.

Use a Separator to place a vertical line between two elements of ribbon item.

Grouping elements in a GroupBar

GroupBar is a container which allows you to group other elements.

GroupBar implements element overflow for the ribbon. Overflow is where elements are removed from the main display and placed into an overflow panel, because the ribbon is not wide enough for them to fit. The overflow panel itself is contained inside a Popup which is opened when the user clicks on the group bar’s overflow button. Elements must be in a GroupBar if they are to participate in overflow.

When a group bar has overflow items, the overflow button is displayed to the right of the elements which are not in overflow and it displays a glyph indicating that it can be pressed. When all the elements in the group bar have been moved into overflow, the overflow button displays the image specified by the group bar’s ImageSource property, if there is one.

A header for the items in the overflow can be set via the group bar’s PopupTitle property.

Like RibbonItem, GroupBar can technically contain any type of UIElement, but it is best to use the controls specifically designed for the ribbon, as listed in the previous section. The only control that cannot be placed into a group bar is a GalleryBar. As usual, in Xaml, elements are added as direct children of the group bar, in code behind the same thing is acomplished by adding elements to the Items collection, and for data binding scenarios bind a collection of data objects to the ItemsSource property.

As the parent window is resized, decreasing in width such not all elements of the selected ribbon fit in the available space, elements will be moved into overflow.

Setting the overflow sequence

The order in which elements are placed into the overflow panel of a group bar is determined by the attached dependency property RibbonItem.OverflowIndex. This property is defined on RibbonItem because, although overflowing is managed by GroupBar, the sequence is defined relative to the containing ribbon item. The sequence begins at 0 and is incremented by one for each successive “jump”, and there cannot be any gaps in the sequence. In other words, the first elements to be placed into overflow are those with OverflowIndex of 0, followed by index of 1, and so on. It is allowed to have multiple elements with the same index. Note that the sequence is defined across all group bars in the ribbon item. For example, say you have two group bars in the ribbon item, group bar A and group bar B. You could have 2 elements in A and 1 element in B with overflow index 0. Overflow index of 1 could be applied to two elements in group bar B. Followed by one element in A with index of 2. And so on.

For convience, all of the controls defined specifically for the ribbon and which are allowed to be children of GroupBar have their own OverflowIndex property,  though they are mapped back to the RibbonItem.OverflowIndex attached property.

Look at the example below. The first two RibbonRadioButton controls will always be at the top level (they will not overflow) because they are not inside a GroupBar. The first item to be hidden in overflow would be the last RibbonCheckBox inside the Show/Hide GroupBar, which has OverflowIndex = 0. The rest would follow according to ascending overflow indexes. The two RibbonButtons with OverflowIndex of 3 will be moved into overflow at the same time. Notice that the first RibbonButton inside the Zoom GroupBar does not have a value for OverflowIndex, indicating that it will never be placed into overflow. While the last element in the same group bar, which has overflow index of –1, will always be in overflow.

<mobile:RibbonItem Header="View">
     <mobile:RibbonRadioButton Content="Edit" IsChecked="True" ImageSource="Images/EditModeIcon.png" />
     <mobile:RibbonRadioButton Content="Read" ImageSource="Images/ReadModeIcon.png" />
     <Separator />
     <mobile:GroupBar PopupTitle="Zoom">
         <mobile:RibbonButton Content="100%" ImageSource="Images/100PercentZoomIcon.png" />
         <mobile:RibbonButton OverflowIndex="3" Content="Zoom Out" />
         <mobile:RibbonButton OverflowIndex="3" Content="Zoom In" />
         <mobile:RibbonCheckBox OverflowIndex="-1" IsChecked="True" Content="Enable Auto Zoom" />
     </mobile:GroupBar>
     <Separator />
     <mobile:GroupBar PopupTitle="Show/Hide" ToolTip="Show/Hide">
         <mobile:RibbonCheckBox OverflowIndex="2" Content="Ruler" />
         <mobile:RibbonCheckBox OverflowIndex="1" Content="Grid" />
         <mobile:RibbonCheckBox OverflowIndex="0" Content="Navigation Pane" />
     </mobile:GroupBar> </mobile:RibbonItem
>

Arranging elements in the overflow

Items are always placed into the overflow panel in their original order, no matter what order they are actually moved into overflow. This cannot be changed. It is, however, possible to specify that adjacent items be placed in the same row. This is accomplished with the attached dependency property GroupBar.OverlowRow, of type Object. Adjacent elements with the same value for OverflowRow will share the same row.

To place a separator between rows, which shows up in the overflow panel but not in the main display, insert a OverflowSeparator control between two items when.

Item selection with a Gallery

Gallery is an ItemsControl with a SelectedItem, and other related properties and events. There are two native container types for items in a gallery, GalleryItem and GalleryCategory. A gallery can contain a collection of either one or the other, or both combined. GalleryItem can be selected. GalleryCategory, on the other hand cannot be selected. Its functions only as a means of organizing items. GalleryCategory is itself an ItemsControl who’s native container type is also GalleryItem. Gallery items which are children of a category are selectable exactly as if they were children of the parent gallery itself. When an item that is contained inside a category is selected, it (or the item for which it is a container) becomes the parent gallery’s selected item.

The gallery’s selected item can be set or read via property SelectedItem. Properties related to SelectedItem are SelectedIndex and Value. SelectedIndex is the index of the selected item with respect to the gallery’s Items collection. In the case where categories are being used, the selected index continues in sequence from the end of one category to the beginning of the next.

Value is determined by the selected item in conjunction with the ValuePath property. If ValuePath is not set, then Value will be equal to SelectedItem. If set, it specifies the property path, relative to the object held by SelectedItem, of the property which is the value of Value. Note that if Value cannot be resolved to an item contained by the gallery (or contained by a category within the gallery) then SelectedItem will be set to null and SelectedIndex -1.

Both Gallery and GalleryCategory have an ItemsPanelOption property, with possible values VerticalSttack, HorizontalStack, VerticalWrap and HorizontalWrap. This property is a short cut to defining a custom ItemsPanel (though you can still use ItemsPanel if you need to.)

Use the Header property of GalleryCategory to specify the category header, and HeaderTemplate to show how to render it.

GalleryItem is a control with an IsSelected property. Setting IsSelectable to false will make the item unselectable. Command and CommandParameter are available if needed, as are the routed events Selected, Unselected and Click. Content and ContentTemplate define, along with ImageSource define the visual appearance.

There are several options for customizing the appearance of a gallery item. One is with the ItemContainerStyle property of the parent gallery, which will be applied to items even when they are inside a category. To define different styles for items in different categories, use the ItemContainerStyle property of GalleryCategory. The ItemTemplate, if set on either Gallery or GalleryCategory, will applied as a gallery item’s ContentTemplate. Finally, it is always possible to define an implicit style targetting GalleryItem.

When using ItemContainerStyle property of Gallery, the style will be applied to either the GalleryCategory or GalleryItem controls it contains, depending on the styles TargetType.

By default a gallery item is animated when pressed. To turn off this behavior use the property DontAnimateWhenPressed.

You might notice that Gallery is a flat container, similiar to a ListBox, and would not fit in the ribbon’s main toolbar. It has to be displayed in a popup. There are two controls that inherit from Gallery, that fit into the ribbon’s main toolbar, and use a popup to show the the gallery items. These are GalleryBar and ComboBox. Another control which can be use to present a gallery in a popup is the RibbonPopupButton. These controls are described next.

Quick access with a GalleryBar.

The GalleryBar control is designed to be a direct descendent of a RibbonItem. In other words, it cannot be placed into a GroupBar, so will always be at the top level and cannot itself be moved into overflow. But it does have overflow of its own.

GalleryBar has two collections. One, the Items collection, which it inherits from Gallery, is displayed in a popup. The other is the QuickAccessItems collection. It is for items that are displayed in the top level, without needing to open the popup. The idea is that the items placed into QuickAccessItems are a subset of the items in the Items collection. Selecting a quick access item causes the corresponding gallery item to be selected as well, and visa-versa. Note that a quick access item need only have value equality with a gallery item. If reference equality is not possible, it is not necessary. Items can be added directly to the QuickAccessItems collection in Xaml or in code. To define the collection in a data binding scenario, create a collection and bind it to the QuiclAccessItemsSource property. Below is an Xaml example showing how to add the quick access with the corresponding gallery items. Notice that the gallery item’s Content will be used to establish equality between the items in the quick access and their corresponding gallery items.

<mobile:GalleryBar PopupTitle="Styles" ToolTip="Styles" QuickAccessOverflowIndexes="5,6,11">
     <mobile:GalleryBar.QuickAccessItems>
         <mobile:GalleryItem Content="Normal" IsSelected="True" />
         <mobile:GalleryItem Content="No Spacing" />
         <mobile:GalleryItem Content="Heading 1" FontSize="18" Foreground="Blue" />
     </mobile:GalleryBar.QuickAccessItems>
     <mobile:GalleryItem Content="Normal" />
     <mobile:GalleryItem Content="No Spacing" />
     <mobile:GalleryItem Content="Heading 1" FontSize="21" Foreground="LightSkyBlue" />
     <mobile:GalleryItem Content="Heading 2" FontSize="18" Foreground="LightSkyBlue" />
     <mobile:GalleryItem Content="Title" FontSize="24" />
</mobile:GalleryBar
>

Use the QuickAccessItemContainerStyle and QuickAccessItemTemplate properties to customize the appearance of the quick access gallery items, or their content.

Similiar to GroupBar, discussed above, GalleryBar has an overflow, which is for the quick access items. Use QuickAccessOverflowIndexes, an enumerable of integer values, to specify the order in which items are moved into overflow. These values will be applied to the quick access items in order, such that the first value in the indexes list is applied to the last quick access item. It is important to note that indexes are relative to the parent RibbonItem, exactly the same as the overflow indexes assigned to items in a GroupBar.

The popup showing the gallery itself is opened with the gallery bar’s overflow button, which is displayed at the right of the quick access items. The content of this button will be a drop down glyph as long as there are visible items in the quick access area. When all items have been moved into overflow, an image is displayed instead. This image is set via GalleryBar’s ImageSource property.

Use IsDropDownOpen to open the popup programmatically.

You can specify the maximum height of the popup with property MaximumPopupHeight.

Use PopupTitle and PopupTitleTemplate specify the popup’s header and how to render it, the same as with GroupBar.

Using RibbonComboBox

RibbonComboBox is the other control which inherits from Gallery. It is not a descendent of the WPF ComboBox. The reason is mainly to support categories. RibbonComboBox does, however, borrow a lot of properties from the standard ComboBox, and behaves much the same way.

Note that the native container type for RibbonComboBox is RibbonComboBoxItem. Use this as the TargetType for an implicit Style definition, or for a Style which is set as value of ItemContainerStyle.

The Header property is provided for convienence. By default, the header is displayed to the left of the actual combo box. HeaderTemplate shows how to render Header.

IsDropDownOpen gets or sets whether the combo box’s drop down is open. MaxDropDownHeight specifies the drop down’s maximum height.

IsEditable specifies whether the selected content is displayed in a TextBox or as content of the popup button. If IsEditable is true, then IsReadOnly is applied to the TextBox and determines whether the user can enter text.

To get or set the text of the editable text box, use the Text property. Note that the text is representative of the combo box’s Value, not its SelectedItem (unless the two are the same.) If the user enters text which converts to a value that is contained in the gallery, then that item is selected. If the value is not in the gallery, then SelectedItem is set to null. If the converstion from text to value fails, then the text in the editable text box is reverted to what it was when the edit began.

The TextChanged routed event is raised when the value of Text changes. The event handler is a RoutedPropertyChangedEventHandler<string>. Here is an example of adding a handler for TextChanged in MainWindow. The following line is from the window’s constructor:

AddHandler(RibbonComboBox.TextChangedEvent, 
new RoutedPropertyChangedEventHandler<string>(RibbonComboBox_TextChanged), false);

And here is the handler itself:

private void RibbonComboBox_TextChanged(object sender, RoutedPropertyChangedEventArgs<string> args)
{
     var comboBox = (RibbonComboBox)args.OriginalSource;
     // Loops through all categories.
     foreach (GalleryCategory category in comboBox.Categories)
     { }
     // Loop through all items, from all categories.
     foreach(object item in comboBox.AllItems)
     { } }

Auto complete is supported when the combo box is editable and not read-only. Property AutoCompleteOption turns auto complete on or off, and defines its behavior. The property is a flags enum with possible values Off, ReadOnly, FreeText and DontConvertCase. Off disables auto complete. ReadOnly enables auto complete while restricting input to values contained by the gallery. FreeText enables auto complete and allows the user to enter any text. DontConvertCase can be or’d to either ReadOnly or FreeText to make auto complete case sensitive.

Like all ribbon controls that are designed to be placed into either a RibbonItem or a GroupBar, RibbonComboBox has both an OverflowIndex property and a SharedOverflowRow property. These are discussed in detail above in the section about GroupBar.

RibbonPopupButton – a general purpose dropdown.

RibbonPopupButton is a HeaderedItemsControl with a toggle button and a popup. When the toggle button is checked, the popup opens to display the items.

RibbonPopupButton does not have a particular native container type, other than ContentPresenter. You can put anything into it that you want – any kind of Visual, or any type of object. If an item is not a Visual (i.e. is a data object or view model object,) be sure to associate a DataTemplate showing how to render it. (To define a DataTemplate for an object, use ItemTemplate or ItemTemplateSelector properties, or define implied DataTemplates for the object type.)

It is possible to put a RibbonPopupButton inside another RibbonPopupButton. When the second button’s popup is opened, it will replace the popup of its parent and there will be a back button beside the popup’s header, allowing the user to close the second popup and return to the first.

Use the IsOpen property to get or set whether the popup is open. MaximumPopupHeight and MaximumPopupWidth define the size of the popup. As usual, PopupTitle sets the header of the popup content, while PopupTitleTemplate shows how to render it. If needed, you can set a padding for the popup content with PopupPadding.

The toggle button’s content is defined by the Header and HeaderTemplatte properties. Use ImageSource to add an Image, with our without a Header. Or, for more flexibility, you can use Icon and IconTemplate in place of ImageSource. A default drop down glyph is added by the default Style.

Related posts:

  1. How to create Backstage application menu in DotNetBar for WPF Ribbon Control
  2. How to build Office 2010 style Backstage application menu with DotNetBar for WPF
  3. How to implement Live Preview using DotNetBar for WPF
  4. WPF AdvToolBar Quick Start Guide
  5. Using Wpf-Ribbon Galleries