--- source_files: - Common/DTS.Common/RegionManager/RegionAdapters/StackPanelRegionAdapter.cs - Common/DTS.Common/RegionManager/RegionAdapters/ViewerStackPanelRegionAdapter.cs generated_at: "2026-04-16T03:27:23.682098+00:00" model: "Qwen/Qwen3-Coder-Next-FP8" schema_version: 1 sha256: "46a3e6b99bc63fd1" --- # RegionAdapters ## Documentation: `StackPanelRegionAdapter` and `ViewerStackPanelRegionAdapter` --- ### 1. Purpose This module provides two Prism region adapters—`StackPanelRegionAdapter` and `ViewerStackPanelRegionAdapter`—that enable Prism region management (view registration, activation, and removal) to work with WPF `StackPanel` controls. Both adapters synchronize the `Views` collection of a Prism `IRegion` with the `Children` collection of a `StackPanel`, enabling declarative region usage in XAML (e.g., `...` attached to a `StackPanel`). They are used to host dynamic, stack-ordered UI content in Prism-based views, with `ViewerStackPanelRegionAdapter` likely reserved for specialized viewer scenarios (e.g., document/image viewers), though its behavior is currently identical to `StackPanelRegionAdapter`. --- ### 2. Public Interface Both classes are public and inherit from `Prism.Regions.RegionAdapterBase`. They expose only the base constructor and the two overridden abstract methods. #### `StackPanelRegionAdapter` - **Constructor** ```csharp public StackPanelRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory) ``` Initializes a new instance of `StackPanelRegionAdapter`, passing `regionBehaviorFactory` to the base class. - **`Adapt` (protected override)** ```csharp protected override void Adapt(IRegion region, StackPanel regionTarget) ``` Attaches a `CollectionChanged` handler to `region.Views`. On `Add`, appends each new `UIElement` in `e.NewItems` to `regionTarget.Children`. On `Remove`, removes each `UIElement` in `e.OldItems` from `regionTarget.Children` *if present*. Does nothing if `region` is `null`. - **`CreateRegion` (protected override)** ```csharp protected override IRegion CreateRegion() ``` Returns a new instance of `AllActiveRegion`, meaning all views added to the region are active simultaneously (no activation/deactivation semantics). #### `ViewerStackPanelRegionAdapter` - **Constructor** ```csharp public ViewerStackPanelRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory) ``` Identical to `StackPanelRegionAdapter` constructor. - **`Adapt` (protected override)** ```csharp protected override void Adapt(IRegion region, StackPanel regionTarget) ``` *Behaviorally identical* to `StackPanelRegionAdapter.Adapt`. - **`CreateRegion` (protected override)** ```csharp protected override IRegion CreateRegion() ``` *Behaviorally identical* to `StackPanelRegionAdapter.CreateRegion`. > **Note**: No additional public methods, properties, or events are defined in either class. --- ### 3. Invariants - **Null Safety**: `Adapt` exits early if `region == null`; no exception is thrown. - **Child Management**: - Views are *always* added to the end of `StackPanel.Children` (order preserved by `Add`). - Views are *only* removed if `regionTarget.Children.Contains(element)` returns `true`; silent no-op otherwise. - No deduplication or uniqueness enforcement: adding the same `UIElement` instance multiple times (e.g., via multiple `Add` actions) will result in multiple children. - **Region Type**: All regions created via `CreateRegion()` are `AllActiveRegion` instances, meaning: - All views in the region are considered active. - No view activation/deactivation lifecycle is enforced by the region itself. - **Event Subscription**: The `CollectionChanged` handler is attached *once* per `Adapt` call and is never detached. Repeated calls to `Adapt` on the same `StackPanel` (e.g., due to re-adapter registration) will result in multiple handlers and duplicate operations. --- ### 4. Dependencies #### Dependencies *of* this module: - **Prism Framework**: Specifically `Prism.Regions.RegionAdapterBase` and `Prism.Regions.IRegionBehaviorFactory`, `IRegion`, `AllActiveRegion`. - **WPF**: `System.Windows.Controls.StackPanel`, `System.Windows.UIElement`. - **.NET Collections**: `System.Collections.Specialized.NotifyCollectionChangedAction`, `NotifyCollectionChangedEventArgs`. #### Dependencies *on* this module: - Likely consumed by Prism region registration logic (e.g., `RegionAdapterMappings`) to map `StackPanel` targets to these adapters. - `ViewerStackPanelRegionAdapter` suggests a domain-specific usage (e.g., in viewer modules), but no explicit consumers are visible in the source. --- ### 5. Gotchas - **Duplicate Event Handlers**: Since `Adapt` does not detach previous handlers, re-adapter registration (e.g., due to module reload or re-initialization) will cause `CollectionChanged` events to be processed multiple times per change, leading to duplicate additions/removals or exceptions (e.g., `ArgumentException` if `Children.Remove` is called on a non-child). This is a critical risk if the adapter is registered multiple times. - **No Cleanup**: No `IDisposable` implementation or handler unsubscription occurs. Long-lived `StackPanel`s with short-lived regions may leak memory if the region is garbage-collected but the handler remains attached. - **Redundant Variable Assignment**: In `Remove` handling, `var element = elementLoopVariable;` is unnecessary (no closure or loop-scope issue in C# 5+), suggesting legacy or defensive coding. - **Identical Implementations**: `StackPanelRegionAdapter` and `ViewerStackPanelRegionAdapter` have *identical* logic. Unless future divergence is intended, this duplication is technical debt. The naming implies a semantic distinction (e.g., viewer-specific behavior), but none is implemented. - **No Exception Handling**: If `Children.Add` or `Children.Remove` throws (e.g., due to cross-thread access or invalid element), the exception propagates unhandled. - **Assumes `StackPanel.Children` is Mutable**: Relies on `StackPanel.Children` being a standard `UIElementCollection`. Custom or mocked `StackPanel` subclasses with non-standard children collections may behave unexpectedly. > **None identified from source alone** for *other* non-obvious behavior beyond the above.