Files

205 lines
16 KiB
Markdown
Raw Permalink Normal View History

2026-04-17 14:55:32 -04:00
---
source_files:
- DTS Viewer/DTS.Viewer/ViewModel/NavigationViewModel.cs
- DTS Viewer/DTS.Viewer/ViewModel/MenuViewModel.cs
- DTS Viewer/DTS.Viewer/ViewModel/ShellViewModel.cs
- DTS Viewer/DTS.Viewer/ViewModel/ViewerShellViewModel.cs
- DTS Viewer/DTS.Viewer/ViewModel/MainViewModel.cs
generated_at: "2026-04-16T14:00:47.869288+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "7a17d7bd36c83744"
---
# DTS Viewer ViewModels Documentation
## 1. Purpose
This module contains the core ViewModel layer for the DTS Viewer WPF application, implementing the MVVM pattern with Prism framework support. It provides the orchestration layer between Views and business logic, managing UI state, region navigation, and inter-component communication via event aggregation. The ViewModels handle shell composition, menu/navigation regions, and main content presentation through Unity dependency injection and Prism's region management system.
---
## 2. Public Interface
### NavigationViewModel
**Signature:** `public class NavigationViewModel : BaseViewModel<INavigationViewModel>, INavigationViewModel`
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `NavigationViewModel(INavigationView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)` | Initializes the view model, sets DataContext, creates interaction requests, and subscribes to `RaiseNotification` event |
| NavigationView | `public INavigationView NavigationView { get; private set; }` | Gets the associated navigation view instance |
| NotificationRequest | `public InteractionRequest<Notification> NotificationRequest { get; private set; }` | Interaction request for displaying notifications |
| ConfirmationRequest | `public InteractionRequest<Confirmation> ConfirmationRequest { get; private set; }` | Interaction request for displaying confirmations |
| Initialize | `public override void Initialize()` | Empty implementation |
| Initialize | `public override void Initialize(object parameter)` | Casts parameter to `IShellViewModel` and assigns to Parent |
| ContextNavigationRegion | `public object ContextNavigationRegion { get; set; }` | Gets/sets content of `NavigationRegion` on the NavigationView |
| HeaderInfo | `public string HeaderInfo { get; }` | Returns `"NavigationRegion"` |
| IsBusy | `public new bool IsBusy { get; set; }` | Throws `NotImplementedException` |
| Activated | `public override void Activated()` | Throws `NotImplementedException` |
| IsDirty | `public new bool IsDirty { get; }` | Throws `NotImplementedException` |
| Cleanup | `public override void Cleanup()` | Throws `NotImplementedException` |
| CleanupAsync | `public new Task CleanupAsync()` | Throws `NotImplementedException` |
| InitializeAsync | `public override Task InitializeAsync()` | Throws `NotImplementedException` |
| InitializeAsync | `public override Task InitializeAsync(object parameter)` | Throws `NotImplementedException` |
---
### MenuViewModel
**Signature:** `public class MenuViewModel : BaseViewModel<IMenuViewModel>, IMenuViewModel`
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `MenuViewModel(IMenuView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)` | Initializes the view model, sets DataContext, creates interaction requests, and subscribes to `RaiseNotification` event |
| View | `public IMenuView View { get; private set; }` | Gets the associated menu view instance |
| NotificationRequest | `public InteractionRequest<Notification> NotificationRequest { get; private set; }` | Interaction request for displaying notifications |
| ConfirmationRequest | `public InteractionRequest<Confirmation> ConfirmationRequest { get; private set; }` | Interaction request for displaying confirmations |
| Initialize | `public override void Initialize()` | Contains placeholder code (`int i = 10;`) |
| Initialize | `public override void Initialize(object parameter)` | Casts parameter to `IShellViewModel` and assigns to Parent |
| CreateViews | `private void CreateViews(Boolean initialize)` | Creates a `ViewDefinition` for `RegionNames.MainRegion` with `IBaseView`/`IBaseViewModel` types (regionManager.AddView call is commented out) |
| HeaderInfo | `public string HeaderInfo { get; }` | Returns `"MainRegion"` |
| IsBusy | `public new bool IsBusy { get; set; }` | Throws `NotImplementedException` |
| Activated | `public override void Activated()` | Throws `NotImplementedException` |
| IsDirty | `public new bool IsDirty { get; }` | Throws `NotImplementedException` |
| Cleanup | `public override void Cleanup()` | Throws `NotImplementedException` |
| CleanupAsync | `public new Task CleanupAsync()` | Throws `NotImplementedException` |
| InitializeAsync | `public override Task InitializeAsync()` | Throws `NotImplementedException` |
| InitializeAsync | `public override Task InitializeAsync(object parameter)` | Throws `NotImplementedException` |
---
### ShellViewModel
**Signature:** `public class ShellViewModel : NotificationObject, IViewerShellViewModel`
| Member | Signature | Description |
|--------|-----------|-------------|
| Attributes | `[Export(typeof(IShellView))]`, `[PartCreationPolicy(CreationPolicy.Shared)]` | MEF export attributes for shared shell view |
| Constructor | `ShellViewModel(IViewerShellView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)` | Initializes view model, subscribes to `RaiseNotification`, registers `IMainView`/`MainView` and `IMainViewModel`/`MainViewModel` (singleton) in Unity container |
| View | `public IViewerShellView View { get; private set; }` | Gets the associated shell view instance |
| NotificationRequest | `public InteractionRequest<Notification> NotificationRequest { get; private set; }` | Interaction request for displaying notifications |
| ConfirmationRequest | `public InteractionRequest<Confirmation> ConfirmationRequest { get; private set; }` | Interaction request for displaying confirmations |
| Initialize | `public void Initialize()` | Contains placeholder code (`int i = 10;`) |
| Initialize | `public void Initialize(object parameter)` | Contains placeholder code (`int i = 22;`) |
| Initialize | `public void Initialize(object parameter, object model)` | Empty implementation |
| Activated | `public void Activated()` | Sets empty string variable |
| GetRegions | `public List<FrameworkElement> GetRegions()` | Uses `Utils.GetChildrenByName` to find elements named "Region" in `MainShell` |
| ContextMainRegion | `public Object ContextMainRegion { get; set; }` | Gets/sets content of `MainRegion` on the ShellView |
| IsMenuIncluded | `public bool IsMenuIncluded { get; set; }` | Gets/sets whether menu is included; raises PropertyChanged |
| IsNavigationIncluded | `public bool IsNavigationIncluded { get; set; }` | Gets/sets whether navigation is included; raises PropertyChanged |
| HeaderInfo | `public string HeaderInfo { get; }` | Returns `"MainRegion"` |
| IsBusy | `public bool IsBusy { get; }` | Throws `NotImplementedException` (getter only) |
| IsDirty | `public bool IsDirty { get; }` | Throws `NotImplementedException` |
| Cleanup | `public void Cleanup()` | Throws `NotImplementedException` |
| CleanupAsync | `public Task CleanupAsync()` | Throws `NotImplementedException` |
| InitializeAsync | `public Task InitializeAsync()` | Throws `NotImplementedException` |
| InitializeAsync | `public Task InitializeAsync(object parameter)` | Throws `NotImplementedException` |
---
### ViewerShellViewModel
**Signature:** `public class ViewerShellViewModel : NotificationObject, IViewerShellViewModel`
| Member | Signature | Description |
|--------|-----------|-------------|
| Attributes | `[Export(typeof(IShellView))]`, `[PartCreationPolicy(CreationPolicy.Shared)]` | MEF export attributes for shared shell view |
| Constructor | `ViewerShellViewModel(IViewerShellView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)` | Initializes view model, subscribes to `RaiseNotification`, registers `IViewerMainView`/`ViewerMainView` and `IViewerMainViewModel`/`ViewerMainViewModel` (singleton) in Unity container |
| View | `public IViewerShellView View { get; private set; }` | Gets the associated viewer shell view instance |
| NotificationRequest | `public InteractionRequest<Notification> NotificationRequest { get; private set; }` | Interaction request for displaying notifications |
| ConfirmationRequest | `public InteractionRequest<Confirmation> ConfirmationRequest { get; private set; }` | Interaction request for displaying confirmations |
| Initialize | `public void Initialize()` | Contains placeholder code (`int i = 10;`) |
| Initialize | `public void Initialize(object parameter)` | Contains placeholder code (`int i = 22;`) |
| Initialize | `public void Initialize(object parameter, object model)` | Empty implementation |
| Activated | `public void Activated()` | Sets empty string variable |
| GetRegions | `public List<FrameworkElement> GetRegions()` | Uses `Utils.GetChildrenByName` to find elements named "Region" in `MainShell` |
| ContextMainRegion | `public Object ContextMainRegion { get; set; }` | Gets/sets content of `MainRegion` on the ViewerShellView |
| IsMenuIncluded | `public bool IsMenuIncluded { get; set; }` | Gets/sets whether menu is included; raises PropertyChanged |
| IsNavigationIncluded | `public bool IsNavigationIncluded { get; set; }` | Gets/sets whether navigation is included; raises PropertyChanged |
| IsBusy | `public bool IsBusy { get; set; }` | **Implemented** - Gets/sets busy state with PropertyChanged notification |
| HeaderInfo | `public string HeaderInfo { get; }` | Returns `"MainRegion"` |
| IsDirty | `public bool IsDirty { get; }` | Throws `NotImplementedException` |
| Cleanup | `public void Cleanup()` | Throws `NotImplementedException` |
| CleanupAsync | `public Task CleanupAsync()` | Throws `NotImplementedException` |
| InitializeAsync | `public Task InitializeAsync()` | Throws `NotImplementedException` |
| InitializeAsync | `public Task InitializeAsync(object parameter)` | Throws `NotImplementedException` |
| OnPropertyChanged | `void IBasePropertyChanged.OnPropertyChanged(string propertyName)` | Throws `NotImplementedException` |
---
### MainViewModel
**Signature:** `public class MainViewModel : BaseViewModel<IMainViewModel>, IMainViewModel`
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `MainViewModel(IMainView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)` | Initializes view model, subscribes to `RaiseNotification` and `AssemblyListNotification` events, registers `IMenuView`/`MenuView`, `IMenuViewModel`/`MenuViewModel`, `INavigationView`/`NavigationView`, `INavigationViewModel`/`NavigationViewModel` in Unity container |
| View | `public IMainView View { get; private set; }` | Gets the associated main view instance |
| NotificationRequest | `public InteractionRequest<Notification> NotificationRequest { get; private set; }` | Interaction request for displaying notifications |
| ConfirmationRequest | `public InteractionRequest<Confirmation> ConfirmationRequest { get; private set; }` | Interaction request for displaying confirmations |
| Initialize | `public override void Initialize()` | Empty implementation |
| Initialize | `public override void Initialize(object parameter)` | Casts parameter to `IViewerShellViewModel`, sets `Parent.IsMenuIncluded` and `Parent.IsNavigationIncluded`, subscribes to `AssemblyListNotification` event |
| Activated | `public override void Activated()` | Empty implementation |
| OnAssemblyListChange | `private void OnAssemblyListChange(AssemblyListInfo e)` | Handler for assembly list changes - **entire implementation is commented out** |
| ContextMainRegion | `public object ContextMainRegion { get; set; }` | Getter returns `null`; setter has commented-out implementation |
| IsMenuIncluded | `public new bool IsMenuIncluded { get; set; }` | Gets/sets menu inclusion flag with PropertyChanged notification |
| IsNavigationIncluded | `public new bool IsNavigationIncluded { get; set; }` | Gets/sets navigation inclusion flag with PropertyChanged notification |
| HeaderInfo | `public string HeaderInfo { get; }` | Returns `"MainRegion"` |
---
## 3. Invariants
1. **Constructor Initialization Order**: All ViewModels must set `View.DataContext = this` before any other initialization in constructors.
2. **Event Subscription Pattern**: All ViewModels subscribe to `RaiseNotification` event via `EventAggregator.GetEvent<RaiseNotification>().Subscribe(OnRaiseNotification)` in their constructors.
3. **Notification Transformation**: `OnRaiseNotification` handlers always transform `NotificationContentEventArgs` to a new instance with `(Message, MessageDetails, Image)` constructor before raising the notification.
4. **Parent Type Casting**: `Initialize(object parameter)` implementations cast the parameter to specific interface types (`IShellViewModel` or `IViewerShellViewModel`) without null checks.
5. **Region Content Access**: `ContextMainRegion` and `ContextNavigationRegion` properties cast their View to the concrete type (e.g., `((ShellView)View)`) to access region content.
6. **MEF Registration**: `ShellViewModel` and `ViewerShellViewModel` are both exported as `IShellView` with `CreationPolicy.Shared`.
7. **Unity Registration Pattern**: View/ViewModel pairs are registered together in constructors (e.g., `RegisterType<IMainView, MainView>()` followed by `RegisterType<IMainViewModel, MainViewModel>()`).
---
## 4. Dependencies
### External Dependencies (Imports)
| Namespace | Purpose |
|-----------|---------|
| `Microsoft.Practices.Prism.Events` | Event aggregation (`IEventAggregator`, pub/sub pattern) |
| `Microsoft.Practices.Prism.Interactivity.InteractionRequest` | `InteractionRequest<T>`, `Notification`, `Confirmation` for UI dialogs |
| `Microsoft.Practices.Prism.Regions` | `IRegionManager` for region-based navigation |
| `Microsoft.Practices.Prism.ViewModel` | `NotificationObject` base class |
| `Microsoft.Practices.Unity` | `IUnityContainer` for dependency injection |
| `System.ComponentModel.Composition` | MEF attributes (`Export`, `PartCreationPolicy`) |
| `System.Windows` | `FrameworkElement` for UI element handling |
### Internal Dependencies
| Namespace | Purpose |
|-----------|---------|
| `DTS.Common.Base` | `BaseViewModel<T>`, `IBaseViewModel`, `IBasePropertyChanged` |
| `DTS.Common.Events` | `RaiseNotification`, `NotificationContentEventArgs`, `AssemblyListNotification`, `AssemblyListInfo` |
| `DTS.Common.Interface` | `INavigationView`, `IMenuView`, `IMainView`, `IViewerShellView`, `IShellViewModel`, `IViewerShellViewModel`, `IMainViewModel`, `IMenuViewModel`, `INavigationViewModel`, `IBaseView`, `IBaseViewModel` |
| `DTS.Common.Classes` | `ViewDefinition` |
| `DTS.Common` | `RegionNames` (contains `MainRegion` constant) |
| `DTS.Common.Utils` | `Utils.GetChildrenByName` static method |
| `DTS.Viewer.View` | Concrete view types: `ShellView`, `ViewerShellView`, `MainView`, `MenuView`, `NavigationView`, `ViewerMainView` |
### Dependency Graph (ViewModel → registers)
- `ShellViewModel` → registers `MainView`/`MainViewModel`
- `ViewerShellViewModel` → registers `ViewerMainView`/`ViewerMainViewModel`
- `MainViewModel` → registers `MenuView`/`MenuViewModel`, `NavigationView`/`NavigationViewModel`
---
## 5. Gotchas
1. **Duplicate MEF Exports**: Both `ShellViewModel` and `ViewerShellViewModel` are exported as `IShellView` with `CreationPolicy.Shared`. This could cause resolution conflicts when importing `IShellView`.
2. **NotImplementedException Landmines**: Multiple critical lifecycle methods throw `NotImplementedException`:
- `Cleanup()`, `CleanupAsync()`, `InitializeAsync()` in all ViewModels
- `IsBusy` getter/setter in `NavigationViewModel`, `MenuViewModel`, `ShellViewModel`
- `IsDirty` getter in all ViewModels
- `Activated()` in `NavigationViewModel` and `MenuViewModel`
Calling these will crash the application.
3. **new Keyword Hiding**: Several properties use `new` keyword to hide base class members (`IsBusy`, `IsDirty`, `IsMenuIncluded`, `IsNavigationIncluded`, `OnPropertyChanged`, `PropertyChanged` event). This can lead to unexpected behavior when casting to base types.
4. **Commented-Out Implementation**: `MainViewModel.OnAssemblyListChange` and `MainViewModel.ContextMainRegion` setter have substantial commented-out code, suggesting incomplete feature implementation. The `ContextMainRegion` getter always returns `null`.
5. **Placeholder Code**: Several `Initialize()` methods contain no-op code