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

151 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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.