Friday, October 14, 2011

Understanding CRM Ribbon XML - Part 3: Group Templates

This is part 3 in a series of posts on customizing CRM ribbons:
- Part 3: Understanding Group Templates (this post)

How do Templates work?

Until now I’ve completely skipped over the templates section of the ribbon xml. This is because Templates can be the most difficult part of ribbon customizations to understand. Templates are used to determine how groups of controls on a ribbon are arranged. The template used will determine the order of the buttons, as well as the size of the buttons. And the template will also determine how the group shrinks when there isn’t enough room on the page for the full ribbon.

For most scenarios (such as adding a button to an existing group) you won’t even need to worry about templates, you can just add the button set it's TemplateAlias attribute to “isv” and you’re done. However, if you are creating a new Group (or a new tab), then it’s worth knowing how Templates work.
First, take a look at the buttons in the UI section. Notice how they each have a TemplateAlias attribute:

Also notice how each Group has a Template Attribute:

If we scroll down to the Templates section, we will find the Template that the group is using. Each Template will have multiple Layouts inside it with names like “LargeMedium”, or “LargeSmall”. One of these Layouts will be used to determine the arrangement of the controls inside the Group (we’ll see how CRM actually decides which layout to use in a bit).

Inside of each layout, there are two ways that the arrangement of buttons and controls can be defined...

1. Layout using OverflowSections

The most common way is using OverflowSections. Each OverflowSection will be arranged in the ribbon group horizontally from left to right, and will contain all the buttons from the group that have the specified TemplateAlias.  This image shows the "Collaborate" group, which is using the "LargeMedium" layout of the "Flexible2" template:

In the image above, all of the buttons using the "o1" templateAlias are placed before all of the buttons with the "o2" TemplateAlias, regardless of their sequence number.  But controls with the same TemplateAlias will be ordered inside the OverflowSection based on their sequence number. In this example there are no buttons currently using the “isv” TemplateAlias, so the isv OverflowSection is not shown at all.
An overflowSection with a Type of “OneRow” will have just a single row of buttons, while a Type of “ThreeRow” will have three rows of buttons stacked on top of eachother.  The DisplayMode determines what size the buttons in the OverflowSection will be. There are three sizes - Large, Medium, and Small:

Notice that all of the default templates each have an OverflowSection for the “isv” templateAlias. This is so developers can easily just add a new button to any group without having to worry about templates or layouts. If you just always use the “isv” TemplateAlias then the button will show up at the end of the group.

2. Layout using Sections and Rows

The other way that Layouts can be defined is using Sections and Rows. Sections and Rows allow the template to have much more precision than OverflowSections when defining the arrangement of controls. Each control in the Group is placed into a specific Section and Row. For example, the Activities group on the “Add Existing” tab uses Sections and Rows to get a very specific arrangement of controls:

Notice that even with the sections and rows in this Layout there are still two OverflowSections at the end of the layout for the "o1" and "isv" TemplateAliases. The Sections and Rows offer more exact control over layout but the OverflowSections off flexibility if you need to add additional custom controls to this group.

Tip: Any time you see a control with a TemplateAlias that starts with “c”, it is using Sections and Rows for layout. Any time the TemplateAlias starts with “o”, it is using OverflowSections (c = ConfrolRef, o = overflowSection).

How does CRM decide which layout to use?

Each template has multiple layouts, and each of these layouts defines how the ribbon group will look at different sizes. This is where the Scaling section comes into play. If you look at the scaling section of a Tab (way back up in the UI section of the xml file), you will see that it maps Groups to Layouts:

The MaxSize element defines which layout the group will use when the ribbon is at its full size. If the user shrinks the window size (reducing the amount of horizontal space available for the ribbon), then it will switch to the next Scale listed.

For each Tab, all of the MaxSize and Scale elements for every groups in a tab are all collected together in one single Scaling element, but if we look at only the Scales for the “Collaborate” group (ignoring all the scales for the other groups), we can see how scales change the layout of the group as horizontal size of the ribbon is decreased:

When the Ribbon is full-width, it uses the first MaxSize scale, which points to the “LargeMedium” layout. As the available width shrinks, it moves to the next Scale in the list, which uses the “LargeSmall” layout. Finally, as the width of the ribbon shrinks further, it reaches the 3rd and final Scale, which uses the “Popup” layout. If you open CRM and navigate to Accounts, you can see how the size of the “collaborate” group changes as you adjust the size of the browser window.

The last Layout in a template is usually a special “Popup” layout. The Popup layout tells CRM which layout to use when the group is shrunk down to its smallest size and becomes a popup menu. The LayoutTitle attribute in the element refers to another layout that is used to arrange the content of the popup (in this case, the popup uses the LargeMedium layout).

How to use this information?

So how do we use this information about templates and scales? Well, if you just need to add a button to an existing group it doesn’t really matter. You can just set button’s TemplateAlias to “isv” and you’re done. However, if you are creating a completely new group for the ribbon then you will need to pick a Template and define the MaxSize and Scaling elements for the group. And if none of the default Templates will work for you, then you can even define your own template in the RibbonDiffXml.

To create a new Group, you will need to do the following:
  1. Add a new Group element to the Tab’s “Groups” collection using a CustomAction.
  2. Add a new MaxSize element into the Tab’s “Scaling” collection using a CustomAction.
  3. Optionally, add additional scales to the scaling collection (it is a good idea to at least add a “Popup” scale).
  4. If you want to specify EnableRules or DisplayRules for the Group, then you will need to create a CommandDefinition for the group, otherwise you can just set the group’s command attribute to “Mscrm.Enabled” (this will make the group always enabled).
  5. Add a new LocLabel to the LocLabels section for the groups Title attribute.
  6. If you defined a Popup scale for the group, then the group should have the Image32by32Popup attribute defined (this is the image shown when the group turns into a popup button at the smallest scale).

In Conclusion...

  1. The arrangement of controls in a ribbon Group is defined by which Template the group is using, and by which TemplateAlias the controls are using.
  2. Template layouts can be defined using either OverflowSections or Sections and Rows.
  3. The layout that CRM uses for a group depends on the MaxSize and Scaling elements defined in the Tab, and also the size of the browser window.
  4. When adding a button to an existing group, you should just use the “isv” TemplateAlias, but when creating new groups you will need to select a Template and define the group’s scaling.
By the way, these posts are meant to supplement the SDK, not replace it, but if there's any part of these posts that you found difficult or confusing please let me know in the comments)

~Erik Pool