This series of CodeProject articles is based on a series of posts I've first published on my blog.
Introduction
In this post, I'll show you how to use the different galleries available with the Windows Ribbon Framework.
The result of this post is a new sample named '09-Galleries' that you can find on the Windows Ribbon for WinForms project page. It looks like this:
Item Galleries vs. Command Galleries
The galleries that we will soon review come in two flavors: item galleries and command galleries. In this section, we will see what's the difference between these two.
Item Galleries
- Gallery items are 'simple' items, just text and image, similar to items in a ComboBox.
- Items have an index and there is a concept of 'Selected Item'.
- Item galleries support preview. This means you get a 'preview' notification (event) when you move over an item, and also a 'cancel preview' notification when you cancel the selection.
- A single item in an item gallery has the following properties:
Label
, Image
, and CategoryID
.
Note: A ComboBox ribbon control is also an item gallery.
Command Galleries
- Gallery items are actually commands.
- The Commands are not indexed and thus don't have the concept of 'Selected Item'.
- Command galleries don't support preview.
- A single item in a command gallery has the following properties:
CommandID
, CommandType
, and CategoryID
.
Note: Both gallery types have the concept of categories, see ComboBox post for more details.
Gallery Types
Now we will review the three gallery types we have, each one can be an item gallery or command gallery. Note that according to MSDN, a ComboBox is also considered to be a gallery which is always an item gallery. Since we already reviewed the ComboBox in a previous post, I won't mention it here.
DropDownGallery
: Just a button, that a click on it displays a list of items. The button itself has no action. In the first image above, the leftmost control is a DropDownGallery
.SplitButtonGallery
: Two buttons, one that is used as a default action, and another one that opens a list of items. In the second image above, the middle control is a SplitButtonGallery
.Note: We already saw in a previous post that the main difference between a DropDown
and a SplitButton
is that a SplitButton
has a default item.
InRibbonGallery
: The items are displayed inside the ribbon, no button is needed. In the images above, the rightmost control is an InRibbonGallery
.
Command Space
One additional feature you should know about, in the sake of completeness, is that all three galleries have a command space. This is a section on the bottom of the control that contains statically defined commands. In the first image above, the DropDownGallery
has a button defined in its command space.
Using the Galleries
In the next sections, I'll show you how to define the galleries in ribbon markup and use the new helper classes for easily operating on them. Note that since the galleries have many options, I will demonstrate only a representative subset.
Using DropDownGallery - Ribbon Markup
Here, I'll show you how to use the DropDownGallery
as an item gallery with a command space. The commands section:
<Application.Commands>
<Command Name='cmdTabMain' Id='1000' LabelTitle='Main' />
<Command Name='cmdGroupDropDownGallery' Id='1001' LabelTitle='Drop Down' />
<Command Name='cmdDropDownGallery' Id='1002' LabelTitle='Size' >
<Command.LargeImages>
<Image>Res/Open32.bmp</Image>
</Command.LargeImages>
<Command.SmallImages>
<Image>Res/Open16.bmp</Image>
</Command.SmallImages>
</Command>
<Command Name='cmdCommandSpace' Id='1003' LabelTitle='Command Space' >
<Command.LargeImages>
<Image>Res/Save32.bmp</Image>
</Command.LargeImages>
<Command.SmallImages>
<Image>Res/Save16.bmp</Image>
</Command.SmallImages>
</Command>
...
</Application.Commands>
Views section:
<Application.Views>
<Ribbon>
<Ribbon.Tabs>
<Tab CommandName='cmdTabMain'>
<Group CommandName='cmdGroupDropDownGallery' SizeDefinition='OneButton'>
<DropDownGallery CommandName='cmdDropDownGallery'
TextPosition='Hide'
Type='Items'>
<DropDownGallery.MenuLayout>
<FlowMenuLayout Columns='1' Rows='5' Gripper='None' />
</DropDownGallery.MenuLayout>
<DropDownGallery.MenuGroups>
<MenuGroup>
<Button CommandName='cmdCommandSpace' />
</MenuGroup>
</DropDownGallery.MenuGroups>
</DropDownGallery>
</Group>
...
</Tab>
</Ribbon.Tabs>
</Ribbon>
</Application.Views>
In the view part, you define the use of a DropDownGallery
along with its layout (how many columns and rows you want) and command space. What makes this gallery an item gallery is setting the Type
attribute to Items
. More details about the DropDownGallery
attributes can be found on MSDN.
Using DropDownGallery - Code-Behind
Create an instance of the RibbonLib.DropDownGallery
helper class and register some of its events:
private Ribbon _ribbon = new Ribbon();
private RibbonDropDownGallery _dropDownGallery;
public Form1()
{
InitializeComponent();
_dropDownGallery = new RibbonDropDownGallery(_ribbon,
(uint)RibbonMarkupCommands.cmdDropDownGallery);
_dropDownGallery.OnExecute += new OnExecuteEventHandler(_dropDownGallery_OnExecute);
_dropDownGallery.OnPreview += new OnPreviewEventHandler(_dropDownGallery_OnPreview);
_dropDownGallery.OnCancelPreview +=
new OnCancelPreviewEventHandler(_dropDownGallery_OnCancelPreview);
}
void _dropDownGallery_OnCancelPreview(PropertyKeyRef key,
PropVariantRef currentValue, IUISimplePropertySet commandExecutionProperties)
{
Console.WriteLine("DropDownGallery::OnCancelPreview");
}
void _dropDownGallery_OnPreview(PropertyKeyRef key,
PropVariantRef currentValue, IUISimplePropertySet commandExecutionProperties)
{
Console.WriteLine("DropDownGallery::OnPreview");
}
void _dropDownGallery_OnExecute(PropertyKeyRef key,
PropVariantRef currentValue, IUISimplePropertySet commandExecutionProperties)
{
Console.WriteLine("DropDownGallery::OnExecute");
}
Add items to the DropDownGallery
:
private void Form1_Load(object sender, EventArgs e)
{
_ribbon.InitFramework(this);
FillDropDownGallery();
}
private void FillDropDownGallery()
{
_dropDownGallery.Label = "Size";
IUICollection itemsSource = _dropDownGallery.ItemsSource;
itemsSource.Clear();
foreach (Image image in imageListLines.Images)
{
itemsSource.Add(new GalleryItemPropertySet()
{
ItemImage = _ribbon.ConvertToUIImage((Bitmap)image)
});
}
}
Note that I'm using a standard ImageList
control here to supply the bitmaps for the DropDownGallery
. GalleryItemPropertySet
is a helper class that represents a single item in an item gallery.
Update (18.11.2009): The updated version of the Ribbon
class provides an implementation for IUICommandHandler
, so the user doesn't need to implement the Execute
and UpdateProperty
methods anymore.
Finally, connect the IUICommandHandler.Execute
and IUICommandHandler.UpdateProperty
methods with the implementation of these methods in the DropDownGallery
class:
public HRESULT Execute(uint commandId, UI_ExecutionVerb verb, ref PropertyKey key,
ref PropVariant currentValue,
IUISimplePropertySet commandExecutionProperties)
{
if (commandId == (uint)RibbonMarkupCommands.cmdDropDownGallery)
{
return _dropDownGallery.Execute(verb, ref key, ref currentValue,
commandExecutionProperties);
}
return HRESULT.S_OK;
}
public HRESULT UpdateProperty(uint commandId, ref PropertyKey key,
ref PropVariant currentValue, ref PropVariant newValue)
{
if (commandId == (uint)RibbonMarkupCommands.cmdDropDownGallery)
{
return _dropDownGallery.UpdateProperty(ref key, ref currentValue, ref newValue);
}
return HRESULT.S_OK;
}
Using SplitButtonGallery - Ribbon Markup
Here, I'll show you how to use the SplitButtonGallery
as a command gallery. Here is the commands section:
<Command Name='cmdGroupSplitButtonGallery' Id='1004' LabelTitle='Split Button' />
<Command Name='cmdSplitButtonGallery' Id='1005' LabelTitle='Brushes' >
<Command.LargeImages>
<Image>Res/Brush1.bmp</Image>
</Command.LargeImages>
</Command>
Views section:
...
<Group CommandName="cmdGroupSplitButtonGallery" SizeDefinition="OneButton">
<SplitButtonGallery CommandName="cmdSplitButtonGallery"
TextPosition="Hide" Type="Commands" HasLargeItems="true">
<SplitButtonGallery.MenuLayout>
<FlowMenuLayout Columns="4" Rows="3" Gripper="None"/>
</SplitButtonGallery.MenuLayout>
</SplitButtonGallery>
</Group>
...
In the view part, you define the use of a SplitButtonGallery
along with its layout (how many columns and rows you want), and optionally, a command space. What makes this gallery a command gallery is setting the Type
attribute to Commands
. More details about the SplitButtonGallery
attributes can be found on MSDN.
Using SplitButtonGallery - Code-Behind
Create an instance of the RibbonLib.SplitButtonGallery
helper class.
private Ribbon _ribbon = new Ribbon();
private RibbonSplitButtonGallery _splitButtonGallery;
private RibbonButton[] _buttons;
public Form1()
{
InitializeComponent();
_splitButtonGallery = new RibbonSplitButtonGallery(_ribbon,
(uint)RibbonMarkupCommands.cmdSplitButtonGallery);
}
Add items to the SplitButtonGallery
:
private void Form1_Load(object sender, EventArgs e)
{
_ribbon.InitFramework(this);
FillSplitButtonGallery();
}
private void FillSplitButtonGallery()
{
_splitButtonGallery.Label = "Brushes";
_buttons = new RibbonButton[imageListBrushes.Images.Count];
uint i;
for (i = 0; i < _buttons.Length; ++i)
{
_buttons[i] = new RibbonButton(_ribbon, 2000 + i)
{
Label = "Label " + i.ToString(),
LargeImage = _ribbon.ConvertToUIImage(
(Bitmap) imageListBrushes.Images[(int) i])
};
}
IUICollection categories = _splitButtonGallery.Categories;
categories.Clear();
categories.Add(new GalleryItemPropertySet() { Label = "Category 1", CategoryID = 1 });
IUICollection itemsSource = _splitButtonGallery.ItemsSource;
itemsSource.Clear();
i = 0;
foreach (Image image in imageListBrushes.Images)
{
itemsSource.Add(new GalleryCommandPropertySet()
{
CommandID = 2000 + i++,
CommandType = CommandType.Action,
CategoryID = 1
});
}
itemsSource.Add(new GalleryCommandPropertySet()
{
CommandID = (uint)RibbonMarkupCommands.cmdSplitButtonGallery,
CommandType = CommandType.Action,
CategoryID = 1
});
}
GalleryCommandPropertySet
is a helper class that represents a single item in a command gallery.
Important: If you don't add the default item to the items list of a SplitButtonGallery
, the items will appear twice! This is probably a bug.
Update (18.11.2009): The updated version of the Ribbon
class provides an implementation for IUICommandHandler
, so the user doesn't need to implement the Execute
and UpdateProperty
methods anymore.
Finally, connect the IUICommandHandler.Execute
and IUICommandHandler.UpdateProperty
methods with the implementation of these methods in the SplitButtonGallery
and Button
classes:
public HRESULT Execute(uint commandId, UI_ExecutionVerb verb, ref PropertyKey key,
ref PropVariant currentValue,
IUISimplePropertySet commandExecutionProperties)
{
if (commandId == (uint)RibbonMarkupCommands.cmdSplitButtonGallery)
{
return _splitButtonGallery.Execute(verb, ref key, ref currentValue,
commandExecutionProperties);
}
else if (commandId >= 2000)
{
return _buttons[commandId - 2000].Execute(verb, ref key, ref currentValue,
commandExecutionProperties);
}
return HRESULT.S_OK;
}
public HRESULT UpdateProperty(uint commandId, ref PropertyKey key,
ref PropVariant currentValue, ref PropVariant newValue)
{
if (commandId == (uint)RibbonMarkupCommands.cmdSplitButtonGallery)
{
return _splitButtonGallery.UpdateProperty(ref key, ref currentValue,
ref newValue);
}
else if (commandId >= 2000)
{
return _buttons[commandId - 2000].UpdateProperty(ref key, ref currentValue,
ref newValue);
}
return HRESULT.S_OK;
}
Note the handling of the dynamically added commands.
Using InRibbonGallery - Ribbon Markup
Here, I'll show you how to use the InRibbonGallery
as an item gallery. Here is the commands section:
<Command Name='cmdGroupInRibbonGallery' Id='1006' LabelTitle='In Ribbon' />
<Command Name='cmdInRibbonGallery' Id='1007' />
Views section:
...
<Group CommandName="cmdGroupInRibbonGallery" SizeDefinition="OneInRibbonGallery">
<InRibbonGallery CommandName="cmdInRibbonGallery" Type="Items"
MaxRows="3" MaxColumns="7">
</InRibbonGallery>
</Group>
...
In the view part, you define the use of a InRibbonGallery
along with its layout. Note that InRibbonGallery
has more control on how to layout its items. More details about the InRibbonGallery
attributes can be found on MSDN.
Using InRibbonGallery - Code-Behind
The code is similar to the DropDownGallery
code. This post is long enough.
That's it for now.