Files
DP44/enriched-qwen3-coder-next/DataPRO/Modules/Hardware/AddEditHardware/ViewModel.md
2026-04-17 14:55:32 -04:00

147 lines
9.7 KiB
Markdown
Raw 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:
- DataPRO/Modules/Hardware/AddEditHardware/ViewModel/AddEditHardwareViewModel.cs
generated_at: "2026-04-16T04:36:54.084304+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "eb93c7718734fde3"
---
# ViewModel
## Documentation: `AddEditHardwareViewModel`
---
### 1. **Purpose**
This module implements the `AddEditHardwareViewModel` class, which serves as the view model for the Add/Edit Hardware UI flow. It encapsulates the logic for displaying, editing, and saving hardware configuration data (e.g., DAS units, SLICE6 devices), including validation, state management, and integration with other system modules (e.g., SLICE6 tree view, event aggregation, region navigation). It supports two operational modes: *adding* new hardware and *editing* existing hardware, and enforces constraints such as disallowing *StandIn* hardware in contexts where it is not permitted (e.g., data recorders). It acts as the intermediary between the UI (`IAddEditHardwareView`) and the underlying domain model (`IAddEditHardwareHardware`, `IISOHardware`), coordinating persistence and inter-module communication via Prism events.
---
### 2. **Public Interface**
#### `AddEditHardwareViewModel(IAddEditHardwareView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)`
- **Behavior**: Primary constructor. Initializes the view, sets up event subscriptions (`RaiseNotification`, `BusyIndicatorChangeNotification`), and assigns dependencies. Assigns `this` as the views `DataContext`.
#### `AddEditHardwareViewModel()`
- **Behavior**: Parameterless constructor required for XAML binding (e.g., design-time or Unity resolution fallback). Does *not* initialize dependencies.
#### `void SetSLICE6TreeView(ISLICE6TreeView treeView, IHardwareListViewModel treeViewModel)`
- **Behavior**: Injects references to the SLICE6 tree view and its view model. Required for SLICE6-specific operations (e.g., saving associations, reloading tree). May be called after construction.
#### `void Activated()`
- **Behavior**: Called when the view is activated. Enforces that `StandIn` is disabled if `AllowStandin` is `false` and the hardware instance is non-null.
#### `void SetHardware(IDASHardware hw, IISOHardware isoHW)`
- **Behavior**: Initializes or resets the `Hardware` property. If `hw` is `null`, creates a new `Model.Hardware` instance; otherwise, constructs a new `Model.Hardware` from the provided `hw` and `isoHW`.
#### `IISOHardware GetISOHardware()`
- **Behavior**: Converts the internal `Hardware` to an `IISOHardware`. If `Hardware.StandIn` is `true` and `SerialNumber` is not a valid GUID, generates a new GUID, updates both `Hardware.SerialNumber` and `isoHW.SerialNumber`, sets `FirstUseDate` to `null`, `IsFirstUseValid` to `true`, and `CalDate` to `DateTime.Today`.
#### `bool Validate(IISOHardware isoHW, ref List<string> errors, ref List<string> warnings, bool displayWindow, bool IsAdd)`
- **Behavior**: Performs validation on `isoHW`. Checks:
- Serial number validity (`ValidateSerialNumber`)
- Uniqueness of serial number *only if* `IsAdd` is `true` (via `Model.Hardware.CheckUniqueSN`)
- IP address validity (`ValidateIPAddress`)
- Appends error/warning messages to `errors`/`warnings`. Calls `PublishPageError` if `displayWindow` is `true`. Returns `false` if any validation fails.
#### `void PublishPageError(bool displayWindow, List<string> errors, List<string> warnings)`
- **Behavior**: If `displayWindow` is `true` and either `errors` or `warnings` is non-empty, publishes a `PageErrorEvent` with combined messages.
#### `void SaveSLICE6Associations()`
- **Behavior**: If `Hardware.HardwareType` is `SLICE6DB`, `SLICE6DB3`, or `SLICE6DB_InDummy`, calls `SLICE6TreeViewModel.SaveSLICE6Associations(Hardware.SerialNumber)`.
#### `void Save()`
- **Behavior**: Persists the current `Hardware` via `Model.Hardware.Save(...)`, passing `TestId`, and `model.IsAdd`. Then:
- Calls `SaveSLICE6Associations()`
- Publishes a `HardwareSavedEvent` with `(DASId, SerialNumber)`
- Calls `SLICE6TreeViewModel.LoadTreeView(SerialNumber)` if `SLICE6TreeViewModel` is non-null.
#### `void NotifyModified()`
- **Behavior**: If `NotificationsOn` is `true`, publishes a `PageModifiedEvent` with status `Modified`.
#### `void Cleanup()`, `Task CleanupAsync()`, `void Initialize()`, `void Initialize(object)`, `void Initialize(object, object)`, `Task InitializeAsync()`, `Task InitializeAsync(object)`, `void Unset()`
- **Behavior**: No-op stubs. Present to satisfy interface contracts (e.g., `IInitialize`, `ICleanup`), but contain no logic.
#### `void OnPropertyChanged(string propertyName)`
- **Behavior**: Raises the `PropertyChanged` event for the specified property.
#### `event PropertyChangedEventHandler PropertyChanged`
- **Behavior**: Standard `INotifyPropertyChanged` implementation.
#### Properties:
- `bool AllowStandin { get; set; } = true`
Controls whether *StandIn* hardware is permitted. Defaults to `true`. Set externally (e.g., `false` for data recorders).
- `IAddEditHardwareView View { get; set; }`
Reference to the associated view.
- `IAddEditHardwareHardware Hardware { get; set; }`
The current hardware instance. Setting it triggers property change notifications for `Hardware`, `SerialNumber`, `FirmwareVersion`, `IPAddress`, and calls `SLICE6TreeViewModel.LoadTreeView(...)`.
- `int? TestId { get; set; }`
Optional test context ID, used during save.
- `bool NotificationsOn { get; set; } = false`
Enables/disables `PageModifiedEvent` publishing.
- `bool IsBusy { get; set; }`
Bound to busy indicator UI. Set via `OnBusyIndicatorNotification`.
- `bool IsMenuIncluded { get; set; }`, `bool IsNavigationIncluded { get; set; }`
UI layout flags; trigger `OnPropertyChanged` on change.
- `ISLICE6TreeView SLICE6TreeView { get; private set; }`, `IHardwareListViewModel SLICE6TreeViewModel { get; private set; }`
References injected via `SetSLICE6TreeView`. May be `null`.
- `InteractionRequest<Notification> NotificationRequest { get; }`, `InteractionRequest<Confirmation> ConfirmationRequest { get; }`
Prism interaction requests used to show popups (e.g., notifications, confirmations).
---
### 3. **Invariants**
- `Hardware` is never `null`; defaults to `new Model.Hardware()` if `SetHardware(null, ...)` is called.
- `Hardware.StandIn` is forced to `false` during `Activated()` if `AllowStandin` is `false` and `Hardware` is non-null.
- `Hardware.SerialNumber` may be overwritten (replaced with a new GUID) in `GetISOHardware()` if `StandIn` is `true` and the current `SerialNumber` is not a valid GUID.
- `Validate(...)` only enforces serial number uniqueness (`CheckUniqueSN`) when `IsAdd` is `true`.
- `IsBusy` is updated synchronously on the publisher thread via `OnBusyIndicatorNotification(bool)`.
- `SLICE6TreeViewModel` may be `null`; all calls to it are guarded with `?.`.
---
### 4. **Dependencies**
#### Imports / Dependencies:
- **Prism Framework**: `IEventAggregator`, `IRegionManager`, `Unity`, `Prism.Events`, `Prism.Interactivity`, `Prism.Regions`.
- **Common Libraries**:
- `DTS.Common.Events.*` (e.g., `RaiseNotification`, `PageModifiedEvent`, `PageErrorEvent`, `HardwareSavedEvent`)
- `DTS.Common.Interface.Hardware.AddEditHardware` (`IAddEditHardwareView`, `IAddEditHardwareHardware`)
- `DTS.Common.Interface.DataRecorders` (`IDASHardware`, `IISOHardware`)
- `DTS.Common.Interface.DASFactory.Diagnostics` (`ISLICE6TreeView`)
- `DTS.Common.Interface.DASFactory.Diagnostics.HardwareList` (`IHardwareListViewModel`)
- `DTS.Common.Utilities.Logging` (`APILogger`)
- `DTS.Common.Interactivity` (`InteractionRequest<...>`)
- `DTS.Common.Enums.Hardware.HardwareTypes` (used in `SaveSLICE6Associations`)
- **Model Layer**: `Model.Hardware` (internal namespace, used for persistence, conversion, validation, and uniqueness checks).
#### Consumed By:
- `IAddEditHardwareView` (XAML view) binds to this view model.
- Other modules (e.g., `HardwareListViewModel`) may call `SetSLICE6TreeView(...)` to wire SLICE6 tree integration.
- Event subscribers for `PageModifiedEvent`, `PageErrorEvent`, `HardwareSavedEvent`.
---
### 5. **Gotchas**
- **Dual constructors**: The parameterless constructor is required for XAML but leaves dependencies (`_eventAggregator`, `_regionManager`, etc.) uninitialized. Calling methods like `Activated()` or `SetHardware(...)` without prior injection may cause `NullReferenceException`.
- **`GetISOHardware()` mutates state**: If `StandIn` is `true` and `SerialNumber` is not a GUID, it *modifies* `Hardware.SerialNumber` and `isoHW.SerialNumber` in-place. This side effect is not obvious from the method name.
- **`Validate(...)` only checks uniqueness on *add***: `CheckUniqueSN` is skipped during edit (`IsAdd == false`), even if the serial number was changed.
- **`SLICE6TreeViewModel.LoadTreeView(...)` is called on `Hardware` setter**: This may trigger expensive tree reloads even when `Hardware` is set to the same instance (e.g., via property binding updates).
- **`NotificationsOn` defaults to `false`**: `NotifyModified()` does nothing unless explicitly enabled. This may lead to missed “page modified” signals if forgotten.
- **`OnRaiseNotification` strips title from `NotificationContentEventArgs`**: The original `eventArgsWithTitle.Title` is used as the popup title, but the message content is reconstructed with an empty string for the third parameter (likely legacy or for compatibility).
- **No-op lifecycle methods**: `Initialize`, `Cleanup`, etc., are present but empty. Developers may assume they do work; they do not.
- **`IsAdd` is not stored in the view model**: It is passed only to `Validate(...)` and `Save(...)`. If the view model is reused across multiple add/edit operations, `IsAdd` must be tracked externally (e.g., via `parameter` or `model.IsAdd`).
None identified beyond the above.