SandRibbon for WPF User Guide

Dynamic Resizing

Back to Table of Contents

Principles

Dynamic resizing refers to the ability of a ribbon to optimize its layout depending on how much screen space is available. This cannot be a fully automatic process, but we do make it easy to specify at design time how you would like the resizing to occur.

Each group in your ribbon tabs can have four distinct sizes. The default size is Large, and the groups will assume their normal, large state whenever they can. After that, there are Medium, Small and Collapsed sizes. You only get to customize the layout for large, medium and small groups. Collapsed groups always look the same - only an image and text is shown, and the user can popup the group to reveal its large size.

To specify size variants for a group you use its Variants collection. This is populated with GroupVariant objects, which have a size and a priority. Although the Variants collection is on RibbonGroup objects, the numeric Priority property of each GroupVariant is applied throughout the ribbon tab as a whole - for all groups. A size variant can only be specified once for each group.

Let us take Microsoft Word as an example, again. The Home tab resizes itself intelligently. Taking it from the point where the window is 1024 pixels wide, and starting to shrink the window, the first thing that happens is that the Editing group shrinks right down to collapsed. Next, the Paragraph group gets smaller, we'll say it goes down to medium, then the Font group does the same. After that, the Styles group shrinks to medium. Now the groups can't rearrange their controls to be any smaller, so they all start to collapse in the order Styles, Paragraph then Font.

The size variants of each ribbon group can be defined directly in XAML, or you can use the designer, which makes things much easier. In the designer, right-click on the ribbon tab and select Edit Size Variations. The size variation editor displays all the potential variations of all the groups on the tab in a box on the right, with all the variations chosen to take effect on the left. Variations can be moved graphically between the boxes, and their relative priorities adjusted. The XAML representing size variations matching Word is as follows:

<sr:RibbonGroup x:Name="ClipboardGroup" Header="Clipboard" ItemSpacing="0" DialogLauncherKeys="FO">
</sr:RibbonGroup>
<sr:RibbonGroup Header="Font" DialogLauncherKeys="FN" sr:KeyboardAccess.Keys="ZF">
	<sr:RibbonGroup.Variants>
		<sr:GroupVariant Variant="Medium" Priority="3" />
		<sr:GroupVariant Variant="Small" Priority="7" />
		<sr:GroupVariant Variant="Collapsed" Priority="8" />
	</sr:RibbonGroup.Variants>
</sr:RibbonGroup>
<sr:RibbonGroup Header="Paragraph" DialogLauncherKeys="FN" sr:KeyboardAccess.Keys="ZP">
	<sr:RibbonGroup.Variants>
		<sr:GroupVariant Variant="Medium" Priority="2" />
		<sr:GroupVariant Variant="Collapsed" Priority="6" />
	</sr:RibbonGroup.Variants>
</sr:RibbonGroup>
<sr:RibbonGroup Header="Styles" DialogLauncherKeys="FY" sr:KeyboardAccess.Keys="ZS">
	<sr:RibbonGroup.Variants>
		<sr:GroupVariant Variant="Medium" Priority="4" />
		<sr:GroupVariant Variant="Collapsed" Priority="5" />
	</sr:RibbonGroup.Variants>
</sr:RibbonGroup>
<sr:RibbonGroup Header="Editing" ShowDialogLauncher="False" sr:KeyboardAccess.Keys="ZN">
	<sr:RibbonGroup.Variants>
		<sr:GroupVariant Variant="Collapsed" Priority="1" />
	</sr:RibbonGroup.Variants>
</sr:RibbonGroup>

The actual controls have been omitted from the above example for clarity. Running the example at this point would do very little; the groups would collapse only.

Layout Containers

The next step to achieving a functional resizing ribbon is to consider the layout containers you need to use in each group. When the group assumes one of its predefined size variants you need a container within to respond to this change. We currently provide two types of container to help with this.

CollapsiblePanel

This panel is not aware of the active size variant, instead it always tries to lay out its children vertically in the small space provided. If it cannot do this, it lays them out horizontally. If you look at the Insert tab in Word, it is full of groups of three large buttons, laid out horizontally, which then become small buttons laid out vertically when the ribbon is shrunk. You would use this panel to achieve such an effect in SandRibbon, combined with the resizing characteristics of buttons, discussed later.

In the designer, you can quickly create this effect by right-clicking on an empty ribbon group and selecting Dynamic Resizing -> Add Collapsible Buttos (3). A CollapsiblePanel is added to the group, and three large buttons added to the panel. When the Medium size variation of the group is activated, the three buttons become smaller and their layout changes to vertical.

LinePanel

This panel has two states. In the normal state it displays its children along two horizontal lines. In the condensed state it displays them along three horizontal lines, more tightly packed together. This is the layout used by the Font and Paragraph groups in Word. You specify the children in row-major order and the panel decides where the break between lines occurs - using the most space efficient position for the break.

The Condense property sets the threshold for when the panel condensed to three lines. Possible values for this property are Never, WhenGroupIsMedium or WhenGroupIsSmall. These values are quite self-explanatory and relate to the active size variant on the group. Taking the example of the Paragraph group above, we decided that its variants (along with the normal large variant) were medium and collapsed. So we would set the Condense property of this panel within to WhenGroupIsMedium.

In the designer, you can quickly create this effect by right-clicking on an empty ribbon group and selecting Dynamic Resizing -> Add 2/3 Line Group. A LinePanel is added to the group, and some buttons added to the panel. When the Medium size variation of the group is activated, the panel rearranges its button group children on to three shorter lines.

At this point, assuming you had filled your panel with buttons, you would have a functioning layout that splits itself into either two or three lines depending on space. There is one more property of interest on LinePanel, however: the CondensedChildOrder property. This allows you to change the order of the panel's children upon being condensed. In the designer, you can right-click on a LinePanel and select Edit Condensed Child Order to graphically alter the order of the panel's children when condensed. The property is a simple Int32Collection that you can set with a comma-delimited list of integers from XAML, if you prefer.

Participating Controls

Specifying the group size variants and choosing the correct panels to use are only two pieces of the puzzle. The final piece is the controls you use, and only once all three are being used together will your ribbon resize itself perfectly.

Button

The control you will use most often is the button control. We have discussed most aspects of it already, including setting its size. You may have noticed that the property to set its size is called NormalSize. This is because the button can shrink itself when it detects that the size variant of its group has changed.


Button has two properties, CollapseToMedium and CollapseToSmall, which are threshold values like the Condense property on LinePanel that we have already discussed. If you have a large button and set its CollapseToMedium property to WhenGroupIsMedium, the button will become medium sized when the active size variant of the group is medium (or indeed small). You can of course also set CollapseToSmall if you like, as well as or instead of CollapseToMedium. If we take the example seen in the Insert tab in Word, we'll use a CollapsiblePanel and put three large buttons in it. Set the CollapseToMedium property for all buttons to WhenGroupIsMedium and assuming the medium size has been defined for that group, the three large horizontally-aligned buttons will collapse to being three medium vertically-aligned buttons.

RibbonGallery

The ribbon gallery can collapse itself too. Normally it has a viewport along with a dropdown button that, when clicked, pops up the gallery. When collapsed, a ribbon gallery shrinks down to simply a large button, that when clicked pops up the gallery. This is why it's important to specify text and image for a ribbon gallery - it can be easy to forget them since they're only used when the gallery is condensed.

To set the threshold at which the ribbon gallery condenses, set its Condense property. This is the now-familiar threshold type, but in this case the default is WhenGroupIsMedium. This means that all you need to do is specify a medium size variant for your group and a ribbon gallery within will automatically collapse when needed. You can of course change it to WhenGroupIsSmall or to Never.

Putting it Together

With the tools discussed above we can quite easily create the entire Home tab of Microsoft Word. This is done by the demonstration application included with the product but we'll do it again here, removing some irrelevant controls. The only panel we need to use is the LinePanel; there are no instances of CollapsiblePanel on the Home tab (but plenty on the Insert tab).

In the Clipboard group we have one large button followed by three medium buttons that become small. This jump from medium to small is the first action when space becomes tight. In the Font group we have five children in a LinePanel, that change their order when the line panel is condensed. Note that the button groups count as child controls, and the buttons within are completely irrelevant as far as the LinePanel is concerned. All it cares about are its direct children. In the Paragraph group there are seven children that also change their order when condensed. The Styles group has a ribbon gallery and a large button and the ribbon gallery does condense itself. Lastly there is an Editing group which has three medium buttons, and the group simply collapses.

<sr:RibbonTab Text="Home" sr:KeyboardAccess.Keys="H">
	<sr:RibbonGroup x:Name="ClipboardGroup" Header="Clipboard" ItemSpacing="0" DialogLauncherKeys="FO">
		<sr:RibbonGroup.Variants>
			<sr:GroupVariant Variant="Medium" Priority="0" />
		</sr:RibbonGroup.Variants>
		<sr:Button Text="Paste" NormalSize="Large" Image="/Icons/paste.png" />
		<StackPanel>
			<sr:Button Text="Cut"  CollapseToSmall="WhenGroupIsMedium" Image="/Icons/cut.png" />
			<sr:Button Text="Copy" CollapseToSmall="WhenGroupIsMedium" Image="/Icons/copy.png" />
			<sr:Button Text="Format Painter" CollapseToSmall="WhenGroupIsMedium" Image="/Icons/color.png" />
		</StackPanel>
	</sr:RibbonGroup>
	<sr:RibbonGroup Header="Font" DialogLauncherKeys="FN" sr:KeyboardAccess.Keys="ZF">
		<sr:RibbonGroup.Variants>
			<sr:GroupVariant Variant="Medium" Priority="3" />
			<sr:GroupVariant Variant="Small" Priority="7" />
			<sr:GroupVariant Variant="Collapsed" Priority="8" />
		</sr:RibbonGroup.Variants>
		<sr:LinePanel CondensedChildOrder="0,3,2,4,1">
			<StackPanel Orientation="Horizontal">
				<sr:ComboBox Width="135" ItemWidth="200" ItemHeight="24" DropDownWidth="201" />
				<sr:ComboBox Width="45" ItemWidth="25" DropDownWidth="26" DropDownHeight="180" />
			</StackPanel>
			<sr:ButtonGroup>
				<sr:Button Command="EditingCommands.IncreaseFontSize" Image="/Icons/font-increasesize.png" />
				<sr:Button Command="EditingCommands.DecreaseFontSize" Image="/Icons/font-decreasesize.png" />
			</sr:ButtonGroup>
			<sr:ButtonGroup>
				<sr:Button Text="Clear Formatting" Image="/Icons/pushpin.png" />
			</sr:ButtonGroup>
			<sr:ButtonGroup>
				<sr:Button Command="EditingCommands.ToggleBold" Image="/Icons/bold.png" />
				<sr:Button Command="EditingCommands.ToggleItalic" Image="/Icons/italic.png" />
				<sr:Button Command="EditingCommands.ToggleUnderline" Image="/Icons/underline.png">
					<sr:RibbonPopup />
				</sr:Button>
				<sr:Button Text="Strikethrough" />
				<sr:Button Command="EditingCommands.ToggleSubscript" />
				<sr:Button Command="EditingCommands.ToggleSuperscript" />
				<sr:Button Text="Change Case" Image="/Icons/fontscheme.png">
					<sr:RibbonPopup />
				</sr:Button>
			</sr:ButtonGroup>
			<sr:ButtonGroup>
				<sr:Button Text="Highlight Color" Image="/Icons/highlight.png">
					<sr:RibbonPopup />
				</sr:Button>
				<sr:Button Text="Font Color" Image="/Icons/fontcolor.png">
					<sr:RibbonPopup />
				</sr:Button>
			</sr:ButtonGroup>
		</sr:LinePanel>
	</sr:RibbonGroup>
	<sr:RibbonGroup Header="Paragraph" DialogLauncherKeys="FN" sr:KeyboardAccess.Keys="ZP">
		<sr:RibbonGroup.Variants>
			<sr:GroupVariant Variant="Medium" Priority="2" />
			<sr:GroupVariant Variant="Collapsed" Priority="6" />
		</sr:RibbonGroup.Variants>
		<sr:LinePanel CondensedChildOrder="0,1,4,5,6,2,3">
			<sr:ButtonGroup>
				<sr:Button Command="EditingCommands.ToggleBullets" Image="/Icons/list-bullets.png">
					<sr:RibbonPopup />
				</sr:Button>
				<sr:Button Command="EditingCommands.ToggleNumbering" Image="/Icons/list-numbered.png">
					<sr:RibbonPopup />
				</sr:Button>
				<sr:Button Text="Multilevel List" Image="/Icons/list-numbered-tb.png">
					<sr:RibbonPopup />
				</sr:Button>
			</sr:ButtonGroup>
			<sr:ButtonGroup>
				<sr:Button Command="EditingCommands.DecreaseIndentation" Image="/Icons/outdent.png" />
				<sr:Button Command="EditingCommands.IncreaseIndentation" Image="/Icons/indent.png" />
			</sr:ButtonGroup>
			<sr:ButtonGroup>
				<sr:Button Text="Sort" Image="/Icons/sortasc.png" />
			</sr:ButtonGroup>
			<sr:ButtonGroup>
				<sr:Button Text="Zoom" Image="/Icons/zoom.png" />
			</sr:ButtonGroup>
			<sr:ButtonGroup>
				<sr:Button Command="EditingCommands.AlignLeft" Image="/Icons/alignleft.png" />
				<sr:Button Command="EditingCommands.AlignCenter" Image="/Icons/aligncenter.png" />
				<sr:Button Command="EditingCommands.AlignRight" Image="/Icons/alignright.png" />
				<sr:Button Command="EditingCommands.AlignJustify" Image="/Icons/alignjustify.png" />
			</sr:ButtonGroup>
			<sr:ButtonGroup>
				<sr:Button Text="Line Spacing" Image="/Icons/expandspace.png">
					<sr:RibbonPopup />
				</sr:Button>
			</sr:ButtonGroup>
			<sr:ButtonGroup>
				<sr:Button Text="Shading" Image="/Icons/linecolor.png">
					<sr:RibbonPopup />
				</sr:Button>
				<sr:Button Text="Borders" Image="/Icons/ruler.png">
					<sr:RibbonPopup />
				</sr:Button>
			</sr:ButtonGroup>
		</sr:LinePanel>
	</sr:RibbonGroup>
	<sr:RibbonGroup Header="Styles" DialogLauncherKeys="FY" sr:KeyboardAccess.Keys="ZS">
		<sr:RibbonGroup.Variants>
			<sr:GroupVariant Variant="Medium" Priority="4" />
			<sr:GroupVariant Variant="Collapsed" Priority="5" />
		</sr:RibbonGroup.Variants>
		<sr:RibbonGallery ItemWidth="72" ItemHeight="56" Text="Quick
Styles" Image="/Icons/users.png">
			<sr:RibbonGallery.Popup>
				<sr:RibbonPopup ResizeMode="Vertical" />
			</sr:RibbonGallery.Popup>
			<sr:GalleryButton />
			<sr:GalleryButton />
			<sr:GalleryButton />
			<sr:GalleryButton />
			<sr:GalleryButton />
			<sr:GalleryButton />
			<sr:GalleryButton />
		</sr:RibbonGallery>
		<sr:Button Text="Change
Styles" NormalSize="Large" Image="/Icons/users.png">
			<sr:RibbonPopup />
		</sr:Button>
	</sr:RibbonGroup>
	<sr:RibbonGroup Header="Editing" sr:KeyboardAccess.Keys="ZN" Image="/Icons/find.png">
		<sr:RibbonGroup.Variants>
			<sr:GroupVariant Variant="Collapsed" Priority="1" />
		</sr:RibbonGroup.Variants>
		<sr:CollapsiblePanel>
			<sr:Button Text="Find" NormalSize="Medium">
				<sr:RibbonPopup />
			</sr:Button>
			<sr:Button Text="Replace" NormalSize="Medium" />
			<sr:Button Text="Select" NormalSize="Medium" />
		</sr:CollapsiblePanel>
	</sr:RibbonGroup>
</sr:RibbonTab>

Next: Live Preview