Files

151 lines
12 KiB
Markdown
Raw Permalink Normal View History

2026-04-17 14:55:32 -04:00
---
source_files:
- Common/DTS.Common/RegionManager/ViewDefinition.cs
- Common/DTS.Common/RegionManager/IDataProRegionManager.cs
- Common/DTS.Common/RegionManager/IDTSRegionManager.cs
- Common/DTS.Common/RegionManager/IDTSViewRegionManager.cs
- Common/DTS.Common/RegionManager/RegionManagerExtensions.cs
- Common/DTS.Common/RegionManager/DataProRegionManager.cs
- Common/DTS.Common/RegionManager/DTSRegionManager.cs
- Common/DTS.Common/RegionManager/DTSViewRegionManager.cs
generated_at: "2026-04-16T02:56:51.813821+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "9e0ce2fec908c09b"
---
# Region Management Module Documentation
## 1. Purpose
This module provides a structured abstraction layer over Prism's region management system for a WPF application, enabling consistent view registration, activation, removal, and data refresh operations across regions using dependency injection and MVVM patterns. It defines a `ViewDefinition` class to declaratively specify view-viewmodel pairs and their target regions, and implements three region manager classes (`DataProRegionManager`, `DTSRegionManager`, `DTSViewRegionManager`) that implement dedicated interfaces (`IDataProRegionManager`, `IDTSRegionManager`, `IDTSViewRegionManager`) to handle view lifecycle operations—including initialization, cleanup, and asynchronous operations—while integrating with Unity container resolution, event aggregation for notifications, and shell view model context updates. The module also provides extension methods (`RegionManagerExtensions`) to augment the base `IRegionManager` with utility operations like clearing, activating, and retrieving views by interface type.
## 2. Public Interface
### `ViewDefinition` Class
- **Constructor**:
`public ViewDefinition(string regionName, Type viewInterfaceType, Type viewModelInterfaceType)`
Creates a view definition specifying the target region, the interface type of the view to be resolved, and the interface type of the viewmodel to be resolved. The `ViewType` property is commented out and unused.
- **Properties**:
- `public string RegionName { get; }` The name of the region where the view will be displayed.
- `public Type ViewInterfaceType { get; }` The interface type used to resolve the view (e.g., `IViewForMyViewModel`).
- `public Type ViewModelInterfaceType { get; }` The interface type used to resolve the viewmodel (e.g., `IMyViewModel`).
- `private ViewDefinition()` Private parameterless constructor; not used in public API.
### `IDataProRegionManager`, `IDTSRegionManager`, `IDTSViewRegionManager` Interfaces
All three interfaces define identical public members (only `IDataProRegionManager` is shown; others are identical in signature):
- `void AddView(ViewDefinition viewDefinition, object parameter)`
Adds a view to its specified region, resolving view and viewmodel via Unity using the types in `viewDefinition`, setting `view.DataContext`, activating the view, and calling `viewModel.Initialize(parameter)` or `viewModel.Initialize()` if `parameter` is null.
- `void AddView(ViewDefinition viewDefinition, object parameter, bool allowMultipleInstances)`
Same as above, but if `allowMultipleInstances` is `false`, attempts to activate an existing view instance (via `ActivateViewIfExists`) and returns early if successful.
- `Task AddViewAsync(ViewDefinition viewDefinition, object parameter)`
Asynchronous version of `AddView(viewDefinition, parameter, false)`.
- `Task AddViewAsync(ViewDefinition viewDefinition, object parameter, bool allowMultipleInstances)`
Asynchronous version of `AddView(viewDefinition, parameter, allowMultipleInstances)`. Uses `InitializeAsync`/`CleanupAsync` where applicable and logs exceptions via `RaiseNotification` event.
- `void RemoveView(IBaseViewModel viewModel)`
Finds all views whose `DataContext` is the given `viewModel` (across all regions), calls `viewModel.Cleanup()`, deactivates and removes each view.
- `void RemoveViewByRegionName(string regionName)`
Clears all views from the specified region using `ClearRegion`.
- `void RefreshView(Type interfaceForView, object parameter)`
Finds all views implementing `interfaceForView` across all regions, calls `viewModel.Cleanup()`, then `viewModel.Initialize(parameter)` or `viewModel.Initialize()`.
- `Task RefreshViewAsync(Type interfaceForView, object parameter)`
Asynchronous version of `RefreshView`, calling `CleanupAsync` and `InitializeAsync`.
> **Note**: The three manager interfaces (`IDataProRegionManager`, `IDTSRegionManager`, `IDTSViewRegionManager`) are functionally identical. Their implementations (`DataProRegionManager`, `DTSRegionManager`, `DTSViewRegionManager`) share nearly identical logic, with minor differences in `GetShellViewModelByRegionName` and region-specific shell context handling (e.g., `NavigationRegion` is only handled in `DataProRegionManager`).
### `RegionManagerExtensions` Class
- `public static void ClearRegion(this IRegionManager regionManager, string regionName)`
Removes all views in the specified region.
- `public static IList<object> GetViews(this IRegionManager regionManager, string regionName, Type interfaceForView)`
Returns all views in the region that are instances of `interfaceForView`.
- `public static object GetView(this IRegionManager regionManager, string regionName, Type interfaceForView)`
Returns the first view in the region that is an instance of `interfaceForView`.
- `public static bool ActivateViewIfExists(this IRegionManager regionManager, string regionName, Type viewType)`
Activates the first view in the region matching `viewType` (if present), returning `true` if activated. Internally calls `ActivateSingleView`, which also invokes `viewModel.Activated()` on the viewmodel.
- `public static void DeactivateViews(this IRegionManager regionManager, string regionName)`
Deactivates all active views in the region.
- `public static void RemoveViews(this IRegionManager regionManager, string regionName)`
Removes all *active* views in the region (note: only active views, not all views).
- `public static void ActivateLastView(this IRegionManager regionManager, string regionName)`
Activates the last active view in the region; if none are active, activates the last view in the regions view collection.
- `public static void AddViewToRegion(this IRegionManager regionManager, string regionName, object view)`
Adds a view to the region without activating.
- `public static void AddViewToRegionActivate(this IRegionManager regionManager, string regionName, object view)`
Adds and immediately activates the view.
- `public static void RemoveView(this IRegionManager regionManager, object view)`
Removes the view from *all* regions it belongs to.
- `public static void RemoveView(this IRegionManager regionManager, string regionName, object view)`
Deactivates and removes the view from the specified region.
## 3. Invariants
- **View-ViewModel Coupling**: Each view must have its `DataContext` set to the resolved viewmodel instance before being added to a region. This is enforced in all `AddView`/`AddViewAsync` implementations.
- **Interface-Based Resolution**: Views and viewmodels are resolved using Unity via their *interface* types (`ViewInterfaceType`, `ViewModelInterfaceType`) stored in `ViewDefinition`. Concrete types are never directly referenced in the manager logic.
- **Lifecycle Order**: For view initialization, `Initialize`/`InitializeAsync` is called *after* the view is added to the region and activated. For view removal, `Cleanup`/`CleanupAsync` is called *before* deactivation/removal.
- **Single Instance Enforcement**: When `allowMultipleInstances` is `false`, `AddViewAsync` attempts to activate an existing view via `ActivateViewIfExists` and returns early if successful—preventing duplicate view instances.
- **Region Context Updates**: After view addition, `IShellViewModel.ContextMainRegion` (and `ContextNavigationRegion` in `DataProRegionManager`) is set to the view instance. This implies that `IShellViewModel` must be resolvable and must expose these properties.
- **Exception Handling**: All `AddViewAsync`, `RefreshViewAsync`, and `RefreshView` methods catch exceptions and publish them via `RaiseNotification` event using `Utility.GetAllErrorMessages(ex)`.
## 4. Dependencies
### Module Dependencies
- **Prism Library**:
- `Prism.Regions` (`IRegionManager`, `IRegionCollection`, `IRegion`)
- `Prism.Events` (`IEventAggregator`, `EventBase` for `RaiseNotification`)
- **Unity Container**: `Unity.IUnityContainer` for DI-based view/viewmodel resolution.
- **Custom Types**:
- `DTS.Common.Base.IBaseView`, `DTS.Common.Base.IBaseViewModel` (for `DataContext`, `Initialize`, `Cleanup`, `Activated`, etc.)
- `DTS.Common.Interface.IShellViewModel` (for `ContextMainRegion`, `ContextNavigationRegion`)
- `DTS.Common.Events.RaiseNotification`, `DTS.Common.Classes.NotificationContentEventArgs`, `DTS.Common.Utility` (for error reporting)
- `DTS.Common.RegionNames` (for region name constants like `MainRegion`, `NavigationRegion`)
### Module Dependents
- Any module or layer requiring region management (e.g., shell initialization, module bootstrapping) depends on one of the `IDTS*RegionManager` interfaces.
- The `RegionManagerExtensions` are used by internal code and other modules to perform region operations beyond the core manager interface.
## 5. Gotchas
- **`ViewType` Property Missing**: The `ViewDefinition` class has a commented-out `ViewType` property and constructor overload. Only interface types are used for resolution—no concrete view/viewmodel types are supported in the current implementation.
- **Redundant Manager Implementations**: `DataProRegionManager`, `DTSRegionManager`, and `DTSViewRegionManager` are nearly identical in implementation. Differences are minimal (e.g., `NavigationRegion` handling only in `DataProRegionManager`). This suggests possible technical debt or legacy branching.
- **`GetShellViewModelByRegionName` Incomplete**: All managers have a `GetShellViewModelByRegionName` method that currently only resolves `IShellViewModel` regardless of region. The commented-out logic suggests future expansion (e.g., per-region shell view models), but it is unused in production code.
- **`RefreshView` / `RefreshViewAsync` Scope**: These methods iterate over *all* regions to find views matching `interfaceForView`. This may cause unintended refreshes if the same view interface is used in multiple regions.
- **`RemoveViews` vs `ClearRegion`**: `RemoveViews` (extension method) only removes *active* views, whereas `ClearRegion` removes *all* views. This distinction may lead to confusion.
- **`AddToRegion`/`RequestNavigate` Not Implemented**: All three region manager classes implement `IRegionManager` but throw `NotImplementedException` for many `IRegionManager` members (e.g., `AddToRegion`, `RegisterViewWithRegion`, `RequestNavigate`). These are not part of the intended public API and should not be used.
- **Async Initialization Assumption**: `InitializeAsync` and `CleanupAsync` are assumed to exist on `IBaseViewModel`. If a concrete viewmodel only implements synchronous methods, runtime errors will occur.
- **`ReferenceEquals` for ViewModel Matching**: `RemoveView` uses `ReferenceEquals` to match viewmodels. This is safe only if viewmodels are singleton-per-region or not shared across views; otherwise, it may fail to find the correct view.
- **No Validation of `ViewDefinition` Inputs**: No null checks or validation of `regionName`, `viewInterfaceType`, or `viewModelInterfaceType` in `ViewDefinition` constructor or manager methods—could lead to runtime resolution failures.