--- source_files: - DTS Viewer/DTS.Viewer.Reports/DTS.Viewer.PSDReport/View/PSDReportMainView.xaml.cs - DTS Viewer/DTS.Viewer.Reports/DTS.Viewer.PSDReport/View/PSDReportMainViewGrid.xaml.cs generated_at: "2026-04-16T13:41:50.267646+00:00" model: "zai-org/GLM-5-FP8" schema_version: 1 sha256: "7e23a726984c27b1" --- # Documentation: DTS.Viewer.PSDReport Views ## 1. Purpose This module provides WPF view components for the PSD (Particle Size Distribution) Report feature within the DTS Viewer application. It contains two partial classes: `PSDReportMainView`, which serves as a shell view implementing `IPSDReportMainView`, and `PSDReportMainViewGrid`, a grid-based view implementing `IPSDReportMainViewGrid` that manages chart tab focus after graph loading completes via event-driven coordination with the application's event aggregator. --- ## 2. Public Interface ### PSDReportMainView (implements `IPSDReportMainView`) | Member | Signature | Description | |--------|-----------|-------------| | Constructor | `public PSDReportMainView()` | Initializes the XAML component. Event handlers for `Loaded`/`Unloaded` are commented out. | ### PSDReportMainViewGrid (implements `IPSDReportMainViewGrid`) | Member | Signature | Description | |--------|-----------|-------------| | Constructor | `public PSDReportMainViewGrid()` | Initializes the XAML component and subscribes to the `Loaded` routed event. | | `_eventAggregator` | `private IEventAggregator` | Backing field for the Prism event aggregator, resolved at runtime. | | `SetFocus` | `private void SetFocus()` | Sets `chartResultsTab` as selected, focusable, and focuses it. | | `PSDReportMainViewGrid_Loaded` | `private void PSDReportMainViewGrid_Loaded(object sender, RoutedEventArgs e)` | Resolves `IEventAggregator` from `ContainerLocator.Container` and subscribes to `GraphLoadedCountNotification`. | | `OnGraphLoadedCountNotification` | `private void OnGraphLoadedCountNotification(GraphLoadedCountNotificationArg arg)` | Handles the graph loaded notification; validates `DataContext` matches `arg.ParentVM`, then waits 3 seconds before invoking `SetFocus()` on the UI thread. | --- ## 3. Invariants - **Event Aggregator Availability**: `_eventAggregator` is resolved in the `Loaded` event handler, ensuring the `ContainerLocator.Container` is initialized before resolution. - **DataContext Type**: The `DataContext` of `PSDReportMainViewGrid` must be castable to `IBaseViewModel` for the notification filtering logic to function correctly. - **Parent VM Matching**: Focus is only set when `arg.ParentVM` matches the view's `DataContext` (cast as `IBaseViewModel`), preventing cross-view interference. - **UI Thread Marshaling**: `Dispatcher.BeginInvoke` is used to marshal the `SetFocus()` call back to the UI thread from the `Task.Run` background context. --- ## 4. Dependencies ### This module depends on: | Namespace | Usage | |-----------|-------| | `DTS.Common.Interface` | `IPSDReportMainView`, `IPSDReportMainViewGrid`, `IBaseViewModel` interfaces | | `DTS.Common.Base` | Base types (exact types unclear from source alone) | | `DTS.Common.Events` | `GraphLoadedCountNotification` event, `GraphLoadedCountNotificationArg` argument class | | `Prism.Ioc` | `ContainerLocator` for service resolution | | `Prism.Events` | `IEventAggregator` for pub/sub messaging | | `System` | `Action` delegate | | `System.Threading` | `Thread.Sleep` | | `System.Threading.Tasks` | `Task.Run` | ### What depends on this module: - Consumers of `IPSDReportMainView` and `IPSDReportMainViewGrid` interfaces (exact consumers unclear from source alone). - XAML files `PSDReportMainView.xaml` and `PSDReportMainViewGrid.xaml` (code-behind relationship). --- ## 5. Gotchas 1. **Hardcoded 3-Second Delay**: `OnGraphLoadedCountNotification` uses `Thread.Sleep(TimeSpan.FromSeconds(3))` to wait for graph rendering. This is a magic number with no configuration or cancellation token, making it brittle if graph rendering time varies. 2. **Commented-Out AvalonDock Serialization**: `PSDReportMainView` contains fully commented-out code for layout serialization/deserialization using `XmlLayoutSerializer` and a `DockManager` element. This suggests either incomplete implementation or intentional removal that was preserved in comments. 3. **Event Subscription Timing**: Per the comment "FB 14797", event subscription is deliberately deferred to the `Loaded` event to ensure `IEventAggregator` availability. This is a workaround for container initialization ordering. 4. **Null-Conditional Pattern**: `_eventAggregator?.GetEvent<...>()` uses null-conditional operator, meaning if the container resolution fails, the subscription silently does nothing. 5. **Multiple ReSharper Suppressions**: The file `PSDReportMainView.xaml.cs` has extensive ReSharper suppressions including `PossibleNullReferenceException`, indicating potential null safety concerns were suppressed rather than handled.