8.6 KiB
source_files, generated_at, model, schema_version, sha256
| source_files | generated_at | model | schema_version | sha256 | |||||
|---|---|---|---|---|---|---|---|---|---|
|
2026-04-16T02:16:32.989533+00:00 | Qwen/Qwen3-Coder-Next-FP8 | 1 | c0e1c8bd7f1a18f4 |
RibbonControl
Documentation: DTS.Common.RibbonControl Module
1. Purpose
This module provides infrastructure for integrating the Microsoft Ribbon control (from the RibbonControlsLibrary) into a Prism-based WPF application, specifically enabling Prism region management and event-driven tab selection coordination for Ribbon and RibbonTab elements. It defines event types for tab selection changes, a behavior to bridge Ribbon.SelectionChanged to Prism events, and a region adapter to manage RibbonTab and RibbonApplicationMenu views within the RibbonRegion. Its role is to decouple view navigation logic from UI controls while preserving Prism’s region-based architecture and enabling reactive tab selection behavior based on view model metadata.
2. Public Interface
RibbonControlSelectionChanged
- Type:
class(inheritsCompositePresentationEvent<RibbonControlSelectionEventArgs>) - Purpose: Prism event used to publish tab selection changes (add/remove operations) on the
Ribbon. - Usage: Subscribers listen for tab operations via
IEventAggregator.GetEvent<RibbonControlSelectionChanged>().Subscribe(...). - Payload:
RibbonControlSelectionEventArgs
RibbonControlOperation
- Type:
enum - Values:
AddedItem: Indicates a tab was added to theRibbon.RemovedItem: Indicates a tab was removed from theRibbon.
RibbonControlSelectionEventArgs
- Type:
class - Properties:
Operation:RibbonControlOperation— the type of operation (AddedItemorRemovedItem).Item:object— theRibbonTab(or other item) involved in the operation.
- Constructor:
RibbonControlSelectionEventArgs(RibbonControlOperation operation, object item)
Initializes the event args with the operation and item.
RibbonControlSelectionChangeBehavior
- Type:
class(inheritsBehavior<Ribbon>) - Properties:
TargetRibbonControl:Ribbon(dependency property) — Note: Property name mismatch in XAML usage; registered as"TargetRibbonControl"but exposed asTargetRibbonControl.
- Behavior:
- Attaches to
Ribbon.SelectionChangedevent. - On selection change, publishes two events (one for
AddedItem, one forRemovedItem) viaRibbonControlSelectionChanged, using the first item ine.AddedItemsande.RemovedItemsrespectively. - Uses
ServiceLocator.Current.GetInstance<IEventAggregator>()to publish events.
- Attaches to
RibbonRegionAdapter
- Type:
class(inheritsRegionAdapterBase<Ribbon>, implementsIDisposable) - Constructor:
RibbonRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory, IRegionManager regionManager, IEventAggregator eventAggregator)- Registers for
RibbonControlSelectionChangedevents via_eventAggregator.GetEvent<TabControlSelectionChanged>().Subscribe(OnTabControlSelectionChanged).
⚠️ Note: Event name mismatch — usesTabControlSelectionChanged(see Gotchas).
- Registers for
- Methods:
Adapt(IRegion region, Ribbon regionTarget):
Subscribes toregion.ActiveViews.CollectionChanged, handlingRibbonTabandRibbonApplicationMenuadditions/removals:- Adds
RibbonTabtoregionTarget.Items, assigns aUidif missing, sorts byTabIndex. - Adds
RibbonApplicationMenutoregionTarget.ApplicationMenu. - Sets
IsSelected = trueon the first added tab ifApp.configcontains<add key="DefaultRibbonTab" value="TabHeaderName"/>.
- Adds
AddRibbonTabToRegion(RibbonTab, Ribbon): Internal helper.AddApplicationMenuToRegion(RibbonApplicationMenu, Ribbon): Internal helper.RemoveRibbonTabFromRibbonRegion(RibbonTab, Ribbon): Removes tab fromRibbon.Items.OnTabControlSelectionChanged(TabControlSelectionEventArgs):
Reacts to tab selection changes:- Ignores
RemovedItemoperations. - Extracts
IBaseView→IRibbonTabInfoProviderfrom view’sDataContext. - Uses
RibbonTabUidto programmatically select the correspondingRibbonTabin the region.
- Ignores
CreateRegion(): Returnsnew AllActiveRegion()(all views remain active).
- IDisposable:
- Unsubscribes from
RibbonControlSelectionChangedinDispose(bool).
- Unsubscribes from
3. Invariants
- Event naming consistency:
RibbonControlSelectionChanged(defined inRibbonControlSelectionChanged.cs) is not the same asTabControlSelectionChanged(used inRibbonRegionAdapter.cs). This is a critical mismatch (see Gotchas). - Item identity:
RibbonControlSelectionEventArgs.Itemis always the first item inAddedItemsorRemovedItems— only single-item operations are handled. - Tab selection logic:
RibbonRegionAdapter.OnTabControlSelectionChangedonly acts onAddedItemoperations and only if:e.Itemis anIBaseView,- its
DataContextimplementsIRibbonTabInfoProvider, IRibbonTabInfoProvider.RibbonTabUidis non-null/non-empty,- and the
RibbonTabwith matchingUidexists in the region.
- UID assignment:
RibbonTab.UidandRibbonApplicationMenu.Uidare auto-generated (viaGuid) if missing duringAdapt().
4. Dependencies
Dependencies of this module:
- Prism libraries:
Microsoft.Practices.Prism.Events,Microsoft.Practices.Prism.Regions,Microsoft.Practices.ServiceLocation. - WPF & Ribbon:
System.Windows,System.Windows.Controls,Microsoft.Windows.Controls.Ribbon(from RibbonControlsLibrary). - Custom types:
DTS.Common.Classes.IBaseViewDTS.Common.Enums.IRibbonTabInfoProviderDTS.Common.Events.TabControlSelectionChanged(note: event name mismatch)DTS.Common.Base.RegionNames.RibbonRegion
Dependencies on this module:
- Application code that uses Prism regions (
RegionNames.RibbonRegion) to hostRibboncontrols. - View models implementing
IRibbonTabInfoProviderto enable programmatic tab selection. - Behaviors or services that subscribe to
RibbonControlSelectionChangedfor tab lifecycle monitoring.
5. Gotchas
-
Event name mismatch:
RibbonRegionAdaptersubscribes toTabControlSelectionChanged, but the event defined in this module isRibbonControlSelectionChanged. This will causeOnTabControlSelectionChangedto never fire, breaking tab selection coordination.
→ Fix required: ChangeTabControlSelectionChangedtoRibbonControlSelectionChangedinRibbonRegionAdapterconstructor andDispose. -
Behavior uses
ServiceLocator:
RibbonControlSelectionChangeBehaviorusesServiceLocator.Current.GetInstance<IEventAggregator>()instead of constructor injection. This violates DI best practices and makes testing harder. -
Single-item assumption:
Only the first added/removed item is used (e.AddedItems[0],e.RemovedItems[0]). Multi-select scenarios (if supported byRibbon) will be silently ignored. -
Property name mismatch:
The dependency property is registered as"TargetRibbonControl"but exposed asTargetRibbonControl. While syntactically valid, this may cause confusion in XAML binding (e.g.,TargetRibbonControl="{Binding ...}"is required — notTargetRibbon). -
Hardcoded config key:
DefaultRibbonTabis read fromApp.configwithout validation or fallback. If the header string doesn’t match exactly (case-insensitive), selection won’t occur. -
No null safety for
Item:
RibbonControlSelectionEventArgs.Itemisobject, but downstream logic (e.g.,OnTabControlSelectionChanged) assumes it is anIBaseView. Casting failures will be silent (viaasoperator). -
Thread-safety via
lock:
AddRibbonTabToRegionuses astatic readonly lock, butRibbonRegionAdapteris instantiated per region (via DI), so the lock is shared across all ribbon regions — potentially causing contention or deadlocks if multiple regions are initialized concurrently. -
Missing
RibbonControlOperationusage:
RibbonControlOperationis defined but only used inRibbonControlSelectionEventArgs. No other code references it directly.
Documentation generated from provided source files. No external behavior or APIs inferred.