--- source_files: - Common/DTS.CommonCore/RibbonControl/RibbonControlSelectionChanged.cs - Common/DTS.CommonCore/RibbonControl/RibbonControlOperation.cs - Common/DTS.CommonCore/RibbonControl/RibbonControlSelectionEventArgs.cs - Common/DTS.CommonCore/RibbonControl/RibbonControlSelectionChangeBehavior.cs - Common/DTS.CommonCore/RibbonControl/RibbonRegionAdapter.cs generated_at: "2026-04-16T12:05:40.425898+00:00" model: "zai-org/GLM-5-FP8" schema_version: 1 sha256: "c0e1c8bd7f1a18f4" --- # RibbonControl Module Documentation ## 1. Purpose This module provides Prism region adapter infrastructure for integrating WPF `Ribbon` controls with the Prism navigation and region system. It enables dynamic addition and removal of `RibbonTab` and `RibbonApplicationMenu` items, synchronizes tab selection between document/workspace views and the Ribbon, and publishes selection change events through the Prism event aggregator for loose coupling between UI components. --- ## 2. Public Interface ### `RibbonControlSelectionChanged` **Kind:** Event class **Signature:** `public class RibbonControlSelectionChanged : CompositePresentationEvent` **Behavior:** A Prism event used to broadcast when a Ribbon's selection has changed. Carries `RibbonControlSelectionEventArgs` payload indicating whether an item was added or removed. --- ### `RibbonControlOperation` **Kind:** Enumeration **Values:** - `AddedItem` — Indicates an item was added to the control - `RemovedItem` — Indicates an item was removed from the control **Behavior:** Used within `RibbonControlSelectionEventArgs` to describe the type of selection operation. --- ### `RibbonControlSelectionEventArgs` **Kind:** Event arguments class **Constructor:** `public RibbonControlSelectionEventArgs(RibbonControlOperation operation, object item)` **Properties:** | Property | Type | Access | |----------|------|--------| | `Operation` | `RibbonControlOperation` | `get;` (set via constructor) | | `Item` | `object` | `get;` (set via constructor) | **Behavior:** Immutable payload carrying the operation type and the affected item for ribbon selection changes. --- ### `RibbonControlSelectionChangeBehavior` **Kind:** WPF Behavior (`System.Windows.Interactivity.Behavior`) **Attached Property:** `public static readonly DependencyProperty TargetRibbonProperty` **Properties:** | Property | Type | Access | |----------|------|--------| | `TargetRibbonControl` | `Ribbon` | `get; set;` | **Methods:** - `protected override void OnAttached()` — Subscribes to `AssociatedObject.SelectionChanged`; resolves `IEventAggregator` via `ServiceLocator.Current` - `protected override void OnDetaching()` — Unsubscribes from `AssociatedObject.SelectionChanged` - `void Ribbon_SelectionChanged(object sender, SelectionChangedEventArgs e)` — Publishes `RibbonControlSelectionChanged` events for each added/removed item **Behavior:** When attached to a `Ribbon`, intercepts selection changes and publishes `RibbonControlSelectionChanged` events. Publishes separate events for added items (first item from `AddedItems`) and removed items (first item from `RemovedItems`). --- ### `RibbonRegionAdapter` **Kind:** Prism RegionAdapter (`RegionAdapterBase`, `IDisposable`) **Constructor:** `public RibbonRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory, IRegionManager regionManager, IEventAggregator eventAggregator)` **Methods:** | Method | Visibility | Description | |--------|------------|-------------| | `Adapt(IRegion region, Ribbon regionTarget)` | `protected override` | Wires up `ActiveViews.CollectionChanged` to add/remove `RibbonTab` and `RibbonApplicationMenu` items | | `CreateRegion()` | `protected override` | Returns new `AllActiveRegion` instance | | `OnTabControlSelectionChanged(TabControlSelectionEventArgs e)` | `private` | Handles `TabControlSelectionChanged` events to sync Ribbon tab selection | | `Dispose()` | `public` | Unsubscribes from `TabControlSelectionChanged` event | **Behavior:** Adapts a `Ribbon` control to a Prism region. Handles `RibbonTab` additions (with auto-generated `Uid`, `TabIndex` sorting, and optional default selection via config), `RibbonApplicationMenu` additions, and `RibbonTab` removals. Listens to `TabControlSelectionChanged` events to activate corresponding Ribbon tabs when views implementing `IRibbonTabInfoProvider` are activated. --- ## 3. Invariants 1. **Null Region Target:** `Adapt()` throws `ArgumentNullException` if `regionTarget` is null. 2. **Region Type:** `CreateRegion()` always returns a new `AllActiveRegion` instance. 3. **Uid Generation:** If a `RibbonTab` or `RibbonApplicationMenu` has a null or empty `Uid`, one is auto-generated using `Guid.NewGuid().GetHashCode().ToString(CultureInfo.InvariantCulture)`. 4. **Tab Sorting:** All `RibbonTab` items added to the region are sorted by `TabIndex` in ascending order. 5. **Single Item Publication:** `RibbonControlSelectionChangeBehavior.Ribbon_SelectionChanged` publishes at most one event for added items (index 0) and one for removed items (index 0), regardless of how many items are in the collections. 6. **Event Subscription Lifecycle:** `RibbonRegionAdapter` unsubscribes from `TabControlSelectionChanged` on disposal. --- ## 4. Dependencies ### This module depends on: - `Microsoft.Practices.Prism.Events` — `CompositePresentationEvent`, `IEventAggregator` - `Microsoft.Practices.Prism.Regions` — `RegionAdapterBase`, `IRegion`, `IRegionBehaviorFactory`, `IRegionManager`, `AllActiveRegion` - `Microsoft.Practices.ServiceLocation` — `ServiceLocator` - `Microsoft.Windows.Controls.Ribbon` — `Ribbon`, `RibbonTab`, `RibbonApplicationMenu` - `System.Windows.Interactivity` — `Behavior` - `System.Configuration` — `ConfigurationManager` - `DTS.Common.Classes` — `IRibbonTabInfoProvider` (referenced but not in source) - `DTS.Common.Enums` — `TabControlOperation` (referenced but not in source) - `DTS.Common.Events` — `TabControlSelectionChanged` event class (referenced but not in source) - `DTS.Common.Base` — `IBaseView` interface (referenced but not in source) ### What depends on this module: - Cannot be determined from source alone; consumers would reference `RibbonRegionAdapter` in Prism bootstrapping/configuration and use `RibbonControlSelectionChanged` event for cross-component communication. --- ## 5. Gotchas 1. **Naming Inconsistency:** The XML documentation comment in `RibbonControlSelectionEventArgs.cs` references "TabControlSelectionChanged" while the actual class is `RibbonControlSelectionChanged`. This may cause confusion. 2. **ServiceLocator vs Constructor Injection:** `RibbonControlSelectionChangeBehavior` resolves `IEventAggregator` via `ServiceLocator.Current.GetInstance()` (service locator pattern), while `RibbonRegionAdapter` receives it via constructor injection. This inconsistency may cause issues in testing or if service locator is not configured. 3. **Partial Lock Coverage:** `AddRibbonTabToRegion()` uses a lock object for thread safety when modifying `regionTarget.Items`, but `RemoveRibbonTabFromRibbonRegion()` does not. This could lead to race conditions in multi-threaded scenarios. 4. **Case-Insensitive Comparison via ToLower():** The `DefaultRibbonTab` configuration comparison uses `ToLower()` on both sides rather than using `StringComparison.OrdinalIgnoreCase`, which is the preferred .NET idiom. 5. **Only First Item Published:** The behavior only publishes events for `e.AddedItems[0]` and `e.RemovedItems[0]`. If multiple items are added/removed in a single selection change, subsequent items are silently ignored. 6. **External Interface Dependencies:** `RibbonRegionAdapter.OnTabControlSelectionChanged()` depends on `IRibbonTabInfoProvider`, `IBaseView`, `TabControlSelectionChanged`, and `TabControlOperation` which are not included in the provided source files. Their contracts are inferred but not documented here.