I had been looking at similar documentation and eventually developed this solution through trial and error, on Visual Studio 2022.
I got the RibbonSplitButton
to produce an area where I could dynamically load buttons, by using the following XAML code...
<RibbonSplitButton x:Name="btnColor" Height="21" Width="40" Margin="-139,-9,139,9" SmallImageSource="images/font-color.png" ToolTip="Font Color" >
<RibbonMenuItem x:Name="itmDefaultColor">
<RibbonMenuItem.Header>
<StackPanel Orientation="Horizontal">
<Rectangle x:Name="rctDefaultColor" Width="13" Height="13" Fill="Transparent" Stroke="Black" Margin="-25,0,15,0"/>
<TextBlock Text="Default Color"/>
</StackPanel>
</RibbonMenuItem.Header>
</RibbonMenuItem>
<RibbonGallery x:Name="galAllColorSwatches" ScrollViewer.VerticalScrollBarVisibility="Disabled">
<RibbonGallery.Resources>
<Style TargetType="Button">
<EventSetter Event="UIElement.PreviewMouseLeftButtonDown" Handler="Button_PreviewMouseLeftButtonDown" />
<EventSetter Event="PreviewKeyDown" Handler="Button_PreviewKeyDown" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="White"/>
</Trigger>
<Trigger Property="IsFocused" Value="True">
<Setter Property="BorderBrush" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="Rectangle">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Stroke" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
</RibbonGallery.Resources>
<RibbonGalleryCategory Header="Custom Colors" FontWeight="Bold" />
<RibbonGallery x:Name="galCustomColors" MinWidth="130" Width="130" MaxWidth="130" ScrollViewer.VerticalScrollBarVisibility="Disabled">
<RibbonGallery.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"></WrapPanel>
</ItemsPanelTemplate>
</RibbonGallery.ItemsPanel>
</RibbonGallery>
<RibbonGalleryCategory Header="Basic Colors" FontWeight="Bold" />
<RibbonGallery x:Name="galBasicColors" MinWidth="130" Width="130" MaxWidth="130" ScrollViewer.VerticalScrollBarVisibility="Disabled">
<RibbonGallery.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"></WrapPanel>
</ItemsPanelTemplate>
</RibbonGallery.ItemsPanel>
</RibbonGallery>
</RibbonGallery>
<RibbonMenuItem x:Name="itmColor" ImageSource="images/font-color.png" Header="Pick Color..."/>
</RibbonSplitButton>
The end result resembles the following image, but requires code to insert the color swatches...

Note there is an outer wrapper RibbonGallery
named galAllColorSwatches
, and that this element has resources set up to respond to specific events when the mouse rolls over buttons that get added dynamically by code, and also to respond to button click events. You could also manually construct all your buttons, and you could potentially add other types of controls in a RibbonGallery.
Creating and inserting a button by code can be accomplished like this in Visual Basic...
' Prepares a button for the color swatch...
Dim [YOUR_BUTTON] As New Button
' Works with the button...
With [YOUR_BUTTON]
.Name = "btnSwatch"
.Content = [INSERT_YOUR_CONTENT_HERE]
.Margin = New Thickness(0, 0, 0, 0)
.Padding = New Thickness(0, 0, 0, 0)
.ToolTip = strColor
.Tag = strColor
End With
' Adds the item to the custom colors...
[YOUR_RIBBONGALLERY_NAME].Items.Add([YOUR_BUTTON])
...but you could also use binding.
If the above code is nested in a For..Next
or similar loop, it can produce a large number of generic buttons like the grid in the image you supplied.
All of the RibbonGalleryCategory
elements are siblings of the RibbonGallery
elements inside the outer wrapper. The inner RibbonGallery
elements each contain RibbonGallery.ItemsPanel
and ItemsPanelTemplate
that helps define the layout for their contents. My example uses WrapPanel
elements to achieve the grid-like layout, but you could potentially add any other compatible element there.
The layout of the content in the WrapPanel
is controlled by the maximum and minimum width settings of the RibbonGallery
elements, and the width settings of the buttons that are dynamically inserted, so you would need to customize those dimensions based on what you intend to achieve.
The top and bottom of the XAML code each have a standard RibbonMenuItem
element. If you nest menu items inside each other, they should produce the standard nested menu with the > indicator. The top item uses a dynamic color swatch that can be loaded with a specific color.