Project DescriptionA RegionAdapter for the Ribbon native WPF control for the PRISM composite WPF application block.
This adapter supports the following:
- Merge RibbonTabs and ContextualTabGroups
- Merge QuickAccessToolBar
- Merge ApplicationMenu
- handle sorting/ordering via attached property
- detect identical tabls/ribbongroups via their Header property or an attached MergeKey property (the attached-property has priority)
- detaches the merged elements from their old parent into the main ribbon, preserving the DataContext of each element
New with Version 0.20:
New with Version 0.11:
- Merge any control which derives from ItemsControl, such as ContextMenu, ListBox, ListView, etc.
- Register the MergingItemsControlRegionAdapter for these controls
Install via nuget:
install-package Prism.RibbonRegionAdapter
Quick-Start
- register the adapter in the Bootstrapper's ConfigureRegionAdapterMappings method:
- mappings.RegisterMapping(typeof(Ribbon), ServiceLocator.Current.GetInstance<Prism.RibbonRegionAdapter.RibbonRegionAdapter>());
- add a "root" ribbon into which all other ribbons are merged and make it a region:
- in each module, which will extend the ribbon, add a UserControl and make it's root element a ribbon control
- in the module's Initialize method, register the module-ribbon with the region
- _regionManager.RegisterViewWithRegion(ShellRegions.Ribbon, typeof(Views.Ribbon));
Affecting merge-order
Use the
UIElementExtension.MergeOrder attached-property on any RibbonTab, RibbonGroup, or Ribbon-Item to affect the merge position
Affecting matching
Use the
UIElementExtension.MergeKey attached-property on any RibbonTab, or RibbonGroup to uniquely identify it, when the corresponding Header property should not be used for matching.
Example Root Ribbon
<Ribbon prism:UIElementExtension.MergeOrder="10"
x:Name="MainMenu" x:FieldModifier="protected internal"
prism:RegionManager.RegionName="{x:Static loc:ShellRegions.MainMenu}">
<RibbonTab Header="General"
prism:UIElementExtension.MergeKey="{x:Static loc:MainMenuMergeKeys.GeneralTab}"
prism:UIElementExtension.MergeOrder="10">
<RibbonGroup Header="Group 1">
<RibbonButton Label="Group1.Button1 (Main)" />
</RibbonGroup>
<RibbonGroup Header="Group 2"
prism:UIElementExtension.MergeKey="{x:Static loc:MainMenuMergeKeys.GeneralTabGroup2}">
<RibbonButton Label="Group2.Button1 (Main)" />
<RibbonButton Label="Group2.Button2 (Main)" />
</RibbonGroup>
</RibbonTab>
<RibbonTab Header="Last Tab"
prism:UIElementExtension.MergeKey="{x:Static loc:MainMenuMergeKeys.LastTab}"
prism:UIElementExtension.MergeOrder="{x:Static sys:Double.MaxValue}">
</RibbonTab>
</Ribbon>
Example Module-Ribbon
<UserControl x:Class="TestApplication.Module1.Ribbon"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:prism="http://www.codeplex.com/prism"
xmlns:loc="clr-namespace:TestApplication"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Ribbon x:Name="MainMenu" x:FieldModifier="protected internal">
<RibbonTab Header="Module1 Tab">
</RibbonTab>
<RibbonTab Header="General (to be merged)"
prism:UIElementExtension.MergeKey="{x:Static loc:MainMenuMergeKeys.GeneralTab}"
prism:UIElementExtension.MergeOrder="10">
<RibbonGroup Header="Group 1b">
<RibbonButton Label="Group1b.Button1 (Module1)" />
<RibbonButton Label="Group1b.Button2 (Module1)" />
</RibbonGroup>
<RibbonGroup Header="Group 2"
prism:UIElementExtension.MergeKey="{x:Static loc:MainMenuMergeKeys.GeneralTabGroup2}">
<RibbonButton Label="Group2.Button1 (Module1, 10)" prism:UIElementExtension.MergeOrder="10" />
<RibbonButton Label="Group2.Button2 (Module1, 99999)" prism:UIElementExtension.MergeOrder="99999" />
</RibbonGroup>
<RibbonGroup Header="Group 3">
<RibbonButton Label="Group3.Button1 (Module1)" />
<RibbonButton Label="Group3.Button2 (Module1)" />
<RibbonButton Label="Group3.Button3 (Module1)" />
</RibbonGroup>
</RibbonTab>
</Ribbon>
</UserControl>
Merging other ItemControl based controls, such as a ContextMenu
First create the context-menu (can be empty, but can also contain initial items) and apply the RegionManager.RegionName attached-property:
<TextBox.ContextMenu>
<ContextMenu prism:RegionManager.RegionName="{x:Static loc:ShellRegions.EditorContextMenu}">
<MenuItem Header="Item 1" />
<MenuItem Header="Item 2">
<MenuItem Header="Item 2.1" />
<MenuItem Header="Item 2.2" />
</MenuItem>
<Separator />
<MenuItem Header="Item 3" />
</ContextMenu>
</TextBox.ContextMenu>
Next create the menu-extensions in the modules (to be able to use the designer, it's best to create UserControls and use it's ContextMenu property):
<UserControl.ContextMenu>
<ContextMenu>
<MenuItem Header="B1 (Module1)" Command="{Binding HelloCommand}" />
<MenuItem Header="B2 override (Module1)"
prism:UIElementExtension.MergeKey="B2 (Main)"
Command="{Binding HelloCommand}">
<MenuItem Header="B2.1 (Module1)" Command="{Binding HelloCommand}" />
</MenuItem>
<MenuItem Header="B3 (Module1) (10)"
prism:UIElementExtension.MergeOrder="10"
Command="{Binding HelloCommand}" />
</ContextMenu>
</UserControl.ContextMenu>
Then register it with the region:
class Module1 : IModule
{
private readonly IRegionManager _regionManager;
public Module1(IRegionManager regionManager)
{
_regionManager = regionManager;
}
public void Initialize()
{
_regionManager.RegisterViewWithRegion(ShellRegions.EditorContextMenu, GetContextMenu);
}
private object GetContextMenu()
{
var cmv = ServiceLocator.Current.GetInstance<EditorContextMenuView>();
cmv.ContextMenu.DataContext = cmv.DataContext;
return cmv.ContextMenu;
}
}
See the included sample-application for usage-details.