156 lines
12 KiB
Markdown
156 lines
12 KiB
Markdown
---
|
||
source_files:
|
||
- Common/DTS.CommonCore/RegionManager/ViewDefinition.cs
|
||
- Common/DTS.CommonCore/RegionManager/IDataProRegionManager.cs
|
||
- Common/DTS.CommonCore/RegionManager/IDTSRegionManager.cs
|
||
- Common/DTS.CommonCore/RegionManager/IDTSViewRegionManager.cs
|
||
- Common/DTS.CommonCore/RegionManager/RegionManagerExtensions.cs
|
||
- Common/DTS.CommonCore/RegionManager/DTSRegionManager.cs
|
||
- Common/DTS.CommonCore/RegionManager/DTSViewRegionManager.cs
|
||
- Common/DTS.CommonCore/RegionManager/DataProRegionManager.cs
|
||
generated_at: "2026-04-16T02:17:34.305643+00:00"
|
||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||
schema_version: 1
|
||
sha256: "716052479006d994"
|
||
---
|
||
|
||
# Region Manager Module Documentation
|
||
|
||
## 1. Purpose
|
||
|
||
This module provides a structured abstraction layer over Prism's `IRegionManager` for managing views and viewmodels in a WPF application using Unity DI. Its primary purpose is to enforce a consistent pattern for view registration, activation, removal, and data refresh operations by leveraging `ViewDefinition` metadata to decouple view/viewmodel instantiation from region management logic. It supports both synchronous and asynchronous operations, handles multiple view instances optionally, and integrates with the application's event aggregation system for error notifications. The module exists to standardize region management across different shell contexts (e.g., `MainRegion`, `NavigationRegion`) and to provide reusable, type-safe operations for view lifecycle management.
|
||
|
||
## 2. Public Interface
|
||
|
||
### `ViewDefinition` Class
|
||
- **`ViewDefinition(string regionName, Type viewInterfaceType, Type viewModelInterfaceType)`**
|
||
Constructor that initializes a view definition with the target region name, the interface type of the view to be resolved, and the interface type of the viewmodel to be resolved. The actual view and viewmodel types are resolved via the DI container using these interfaces.
|
||
|
||
- **`string RegionName { get; }`**
|
||
Gets the name of the region where the view will be displayed.
|
||
|
||
- **`Type ViewInterfaceType { get; }`**
|
||
Gets the interface type used to resolve the view instance (e.g., `IBaseView` or a custom view interface).
|
||
|
||
- **`Type ViewModelInterfaceType { get; }`**
|
||
Gets the interface type used to resolve the viewmodel instance (e.g., `IBaseViewModel` or a custom viewmodel interface).
|
||
|
||
> **Note**: The `ViewType` and `ViewModelType` properties are commented out in the source and not used.
|
||
|
||
### `IDataProRegionManager`, `IDTSRegionManager`, `IDTSViewRegionManager` Interfaces
|
||
All three interfaces are *identical* in signature and define the same contract. They extend `IRegionManager` and add the following methods:
|
||
|
||
- **`void AddView(ViewDefinition viewDefinition, object parameter)`**
|
||
Adds a view to the region specified in `viewDefinition`, using `parameter` to initialize the viewmodel. Does *not* allow multiple instances (delegates to `AddView(viewDefinition, parameter, false)`).
|
||
|
||
- **`void AddView(ViewDefinition viewDefinition, object parameter, bool allowMultipleInstances)`**
|
||
Adds a view to the region specified in `viewDefinition`. If `allowMultipleInstances` is `false`, attempts to activate an existing view of the same type instead of adding a new one.
|
||
|
||
- **`Task AddViewAsync(ViewDefinition viewDefinition, object parameter)`**
|
||
Asynchronous version of `AddView(viewDefinition, parameter)`.
|
||
|
||
- **`Task AddViewAsync(ViewDefinition viewDefinition, object parameter, bool allowMultipleInstances)`**
|
||
Asynchronous version of `AddView(viewDefinition, parameter, allowMultipleInstances)`.
|
||
|
||
- **`void RemoveView(IBaseViewModel viewModel)`**
|
||
Removes *all* views associated with the given `viewModel` from *all* regions. Calls `Cleanup()` on the viewmodel before removal.
|
||
|
||
- **`void RemoveViewByRegionName(string regionName)`**
|
||
Clears *all* views from the specified region by calling `ClearRegion(regionName)`.
|
||
|
||
- **`void RefreshView(Type interfaceForView, object parameter)`**
|
||
Finds *all* views of type `interfaceForView` across *all* regions, calls `Cleanup()` on their viewmodels, and reinitializes them with `parameter` (or `null` if none provided). Synchronous.
|
||
|
||
- **`Task RefreshViewAsync(Type interfaceForView, object parameter)`**
|
||
Asynchronous version of `RefreshView`. Calls `CleanupAsync()` and `InitializeAsync()` on the viewmodels.
|
||
|
||
### `RegionManagerExtensions` Class (Static)
|
||
Provides utility extension methods for `IRegionManager`:
|
||
|
||
- **`void ClearRegion(this IRegionManager regionManager, string regionName)`**
|
||
Removes all views from the specified region.
|
||
|
||
- **`IList<object> GetViews(this IRegionManager regionManager, string regionName, Type interfaceForView)`**
|
||
Returns a list of views in the region that implement `interfaceForView`.
|
||
|
||
- **`object GetView(this IRegionManager regionManager, string regionName, Type interfaceForView)`**
|
||
Returns the *first* view in the region that implements `interfaceForView`.
|
||
|
||
- **`bool ActivateViewIfExists(this IRegionManager regionManager, string regionName, Type viewType)`**
|
||
Activates the first view of `viewType` in the region if it exists. Returns `true` if activated, `false` otherwise. Internally calls `ActivateSingleView`, which also invokes `viewModel.Activated()` on the viewmodel.
|
||
|
||
- **`void DeactivateViews(this IRegionManager regionManager, string regionName)`**
|
||
Deactivates all currently active views in the region.
|
||
|
||
- **`void RemoveViews(this IRegionManager regionManager, string regionName)`**
|
||
Removes all *active* views from the region.
|
||
|
||
- **`void ActivateLastView(this IRegionManager regionManager, string regionName)`**
|
||
Activates the last active view in the region, or if none are active, the last view in the region’s view collection.
|
||
|
||
- **`void AddViewToRegion(this IRegionManager regionManager, string regionName, object view)`**
|
||
Adds a view to the region without activating it.
|
||
|
||
- **`void AddViewToRegionActivate(this IRegionManager regionManager, string regionName, object view)`**
|
||
Adds and activates a view in the region.
|
||
|
||
- **`void RemoveView(this IRegionManager regionManager, object view)`**
|
||
Removes the view from *all* regions it belongs to.
|
||
|
||
- **`void RemoveView(this IRegionManager regionManager, string regionName, object view)`**
|
||
Deactivates and removes the view from the specified region.
|
||
|
||
### `DTSRegionManager`, `DTSViewRegionManager`, `DataProRegionManager` Classes
|
||
All three classes implement their respective interfaces (`IDTSRegionManager`, `IDTSViewRegionManager`, `IDataProRegionManager`) and are functionally *identical* in behavior. They differ only in the interface they implement and minor variations in `GetShellViewModelByRegionName` logic (see *Gotchas*). They share the same constructor:
|
||
|
||
- **`DTSRegionManager(IUnityContainer unityContainer, IRegionManager regionManager, IEventAggregator eventAggregator)`**
|
||
Constructor injecting Unity container, Prism region manager, and event aggregator.
|
||
|
||
All method implementations are as described in the interfaces above.
|
||
|
||
## 3. Invariants
|
||
|
||
- **`ViewDefinition` must specify non-null `regionName`, `viewInterfaceType`, and `viewModelInterfaceType`** — enforced by constructor parameters; null values are not validated but will cause runtime errors during resolution.
|
||
- **All `AddView`/`AddViewAsync` operations resolve view and viewmodel via `IUnityContainer` using `viewInterfaceType` and `viewModelInterfaceType`** — the actual concrete types must be registered in the container.
|
||
- **`IBaseView.DataContext` must be set to the resolved `IBaseViewModel` before adding to region** — enforced in `AddView`/`AddViewAsync` implementations.
|
||
- **`IBaseViewModel.Initialize` or `InitializeAsync` is called after view registration** — initialization is deferred until after view is added to region and bound to viewmodel.
|
||
- **`RemoveView(IBaseViewModel)` removes *all* views associated with the viewmodel from *all* regions** — not limited to a single region.
|
||
- **`RefreshView`/`RefreshViewAsync` iterates over *all* regions** — not region-specific, and may affect views in unintended regions.
|
||
- **`allowMultipleInstances = false` prevents duplicate view instances** — by attempting to activate an existing view instead of adding a new one.
|
||
- **`ClearRegion`/`RemoveViewByRegionName` removes *all* views in the region** — no selective removal.
|
||
|
||
## 4. Dependencies
|
||
|
||
### Module Dependencies
|
||
- **`Microsoft.Practices.Prism.Regions`** — Provides `IRegionManager`, `IRegionCollection`, `IRegion`, and `IRegionManager` base types.
|
||
- **`Microsoft.Practices.Unity`** — Provides `IUnityContainer` for DI.
|
||
- **`DTS.Common.Base`** — Defines `IBaseView`, `IBaseViewModel`, and `IBaseViewModel` interface methods (`Initialize`, `InitializeAsync`, `Cleanup`, `CleanupAsync`, `Activated`).
|
||
- **`DTS.Common.Events`** — Defines `RaiseNotification` event and `NotificationContentEventArgs`.
|
||
- **`DTS.Common.Classes`** — Used for `Utility.GetAllErrorMessages(ex)` (error aggregation).
|
||
- **`DTS.Common.Interface`** — Defines `IShellViewModel` and region name constants (e.g., `RegionNames.MainRegion`, `RegionNames.NavigationRegion`).
|
||
|
||
### Dependencies *on* This Module
|
||
- Any module or service that needs to manage views in Prism regions (e.g., shell initialization, module loading, user navigation).
|
||
- Likely consumed via DI as `IDTSRegionManager`, `IDTSViewRegionManager`, or `IDataProRegionManager` depending on the shell context.
|
||
|
||
## 5. Gotchas
|
||
|
||
- **`ViewType` and `ViewModelType` properties are commented out** — The class only stores interface types (`ViewInterfaceType`, `ViewModelInterfaceType`), not concrete types. This is intentional but may be confusing if one expects full type metadata.
|
||
|
||
- **Three region manager implementations with identical logic** — `DTSRegionManager`, `DTSViewRegionManager`, and `DataProRegionManager` are near-duplicates. Only `DataProRegionManager.GetShellViewModelByRegionName` has region-specific logic (resolves `IShellViewModel` only for `MainRegion`), while the others resolve unconditionally. This duplication suggests technical debt or incomplete refactoring.
|
||
|
||
- **`AddViewAsync` does not guarantee thread safety** — Although `async`, it performs UI-bound operations (view resolution, setting `DataContext`, region operations) on the calling thread (likely the UI thread due to Prism’s region manager). No explicit dispatcher marshaling is visible.
|
||
|
||
- **`RefreshView`/`RefreshViewAsync` may affect multiple regions unintentionally** — They iterate over *all* regions and refresh *all* views matching `interfaceForView`, which could cause unexpected side effects if the same view type is used in multiple regions.
|
||
|
||
- **`RemoveViewByRegionName` uses `ClearRegion`** — This removes *all* views in the region, not just those associated with a specific viewmodel or view type.
|
||
|
||
- **`ActivateViewIfExists` returns `false` if view does not exist** — But does *not* add or create the view; callers must handle this case explicitly.
|
||
|
||
- **`GetShellViewModelByRegionName` is incomplete** — In `DTSRegionManager` and `DTSViewRegionManager`, it always resolves `IShellViewModel` regardless of region. In `DataProRegionManager`, it only resolves for `MainRegion`. This inconsistency may lead to `ContextMainRegion` not being set for other regions.
|
||
|
||
- **No validation of `parameter` type or nullability** — `Initialize`/`InitializeAsync` are called with the raw `parameter` object; if the viewmodel does not support the provided parameter, runtime errors may occur.
|
||
|
||
- **Error handling uses event aggregation** — Exceptions in `AddViewAsync`, `RefreshView`, and `RefreshViewAsync` are caught and published via `RaiseNotification`. Callers must subscribe to this event to be notified of failures.
|
||
|
||
- **`RemoveView` uses `ReferenceEquals` for viewmodel matching** — This relies on reference equality of viewmodels, which may not hold if viewmodels are recreated or compared by value. |