Files
2026-04-17 14:55:32 -04:00

8.6 KiB
Raw Permalink Blame History

source_files, generated_at, model, schema_version, sha256
source_files generated_at model schema_version sha256
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
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 Prisms region-based architecture and enabling reactive tab selection behavior based on view model metadata.


2. Public Interface

RibbonControlSelectionChanged

  • Type: class (inherits CompositePresentationEvent<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 the Ribbon.
    • RemovedItem: Indicates a tab was removed from the Ribbon.

RibbonControlSelectionEventArgs

  • Type: class
  • Properties:
    • Operation: RibbonControlOperation — the type of operation (AddedItem or RemovedItem).
    • Item: object — the RibbonTab (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 (inherits Behavior<Ribbon>)
  • Properties:
    • TargetRibbonControl: Ribbon (dependency property) — Note: Property name mismatch in XAML usage; registered as "TargetRibbonControl" but exposed as TargetRibbonControl.
  • Behavior:
    • Attaches to Ribbon.SelectionChanged event.
    • On selection change, publishes two events (one for AddedItem, one for RemovedItem) via RibbonControlSelectionChanged, using the first item in e.AddedItems and e.RemovedItems respectively.
    • Uses ServiceLocator.Current.GetInstance<IEventAggregator>() to publish events.

RibbonRegionAdapter

  • Type: class (inherits RegionAdapterBase<Ribbon>, implements IDisposable)
  • Constructor:
    RibbonRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory, IRegionManager regionManager, IEventAggregator eventAggregator)
    
    • Registers for RibbonControlSelectionChanged events via _eventAggregator.GetEvent<TabControlSelectionChanged>().Subscribe(OnTabControlSelectionChanged).
      ⚠️ Note: Event name mismatch — uses TabControlSelectionChanged (see Gotchas).
  • Methods:
    • Adapt(IRegion region, Ribbon regionTarget):
      Subscribes to region.ActiveViews.CollectionChanged, handling RibbonTab and RibbonApplicationMenu additions/removals:
      • Adds RibbonTab to regionTarget.Items, assigns a Uid if missing, sorts by TabIndex.
      • Adds RibbonApplicationMenu to regionTarget.ApplicationMenu.
      • Sets IsSelected = true on the first added tab if App.config contains <add key="DefaultRibbonTab" value="TabHeaderName"/>.
    • AddRibbonTabToRegion(RibbonTab, Ribbon): Internal helper.
    • AddApplicationMenuToRegion(RibbonApplicationMenu, Ribbon): Internal helper.
    • RemoveRibbonTabFromRibbonRegion(RibbonTab, Ribbon): Removes tab from Ribbon.Items.
    • OnTabControlSelectionChanged(TabControlSelectionEventArgs):
      Reacts to tab selection changes:
      • Ignores RemovedItem operations.
      • Extracts IBaseViewIRibbonTabInfoProvider from views DataContext.
      • Uses RibbonTabUid to programmatically select the corresponding RibbonTab in the region.
    • CreateRegion(): Returns new AllActiveRegion() (all views remain active).
  • IDisposable:
    • Unsubscribes from RibbonControlSelectionChanged in Dispose(bool).

3. Invariants

  • Event naming consistency:
    RibbonControlSelectionChanged (defined in RibbonControlSelectionChanged.cs) is not the same as TabControlSelectionChanged (used in RibbonRegionAdapter.cs). This is a critical mismatch (see Gotchas).
  • Item identity:
    RibbonControlSelectionEventArgs.Item is always the first item in AddedItems or RemovedItems — only single-item operations are handled.
  • Tab selection logic:
    RibbonRegionAdapter.OnTabControlSelectionChanged only acts on AddedItem operations and only if:
    • e.Item is an IBaseView,
    • its DataContext implements IRibbonTabInfoProvider,
    • IRibbonTabInfoProvider.RibbonTabUid is non-null/non-empty,
    • and the RibbonTab with matching Uid exists in the region.
  • UID assignment:
    RibbonTab.Uid and RibbonApplicationMenu.Uid are auto-generated (via Guid) if missing during Adapt().

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.IBaseView
    • DTS.Common.Enums.IRibbonTabInfoProvider
    • DTS.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 host Ribbon controls.
  • View models implementing IRibbonTabInfoProvider to enable programmatic tab selection.
  • Behaviors or services that subscribe to RibbonControlSelectionChanged for tab lifecycle monitoring.

5. Gotchas

  • Event name mismatch:
    RibbonRegionAdapter subscribes to TabControlSelectionChanged, but the event defined in this module is RibbonControlSelectionChanged. This will cause OnTabControlSelectionChanged to never fire, breaking tab selection coordination.
    Fix required: Change TabControlSelectionChanged to RibbonControlSelectionChanged in RibbonRegionAdapter constructor and Dispose.

  • Behavior uses ServiceLocator:
    RibbonControlSelectionChangeBehavior uses ServiceLocator.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 by Ribbon) will be silently ignored.

  • Property name mismatch:
    The dependency property is registered as "TargetRibbonControl" but exposed as TargetRibbonControl. While syntactically valid, this may cause confusion in XAML binding (e.g., TargetRibbonControl="{Binding ...}" is required — not TargetRibbon).

  • Hardcoded config key:
    DefaultRibbonTab is read from App.config without validation or fallback. If the header string doesnt match exactly (case-insensitive), selection wont occur.

  • No null safety for Item:
    RibbonControlSelectionEventArgs.Item is object, but downstream logic (e.g., OnTabControlSelectionChanged) assumes it is an IBaseView. Casting failures will be silent (via as operator).

  • Thread-safety via lock:
    AddRibbonTabToRegion uses a static readonly lock, but RibbonRegionAdapter is 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 RibbonControlOperation usage:
    RibbonControlOperation is defined but only used in RibbonControlSelectionEventArgs. No other code references it directly.


Documentation generated from provided source files. No external behavior or APIs inferred.