101 lines
6.6 KiB
Markdown
101 lines
6.6 KiB
Markdown
|
|
---
|
|||
|
|
source_files:
|
|||
|
|
- DataPRO/Modules/ISO/ExtraProperties/Model/ExtraPropertyModel.cs
|
|||
|
|
generated_at: "2026-04-16T04:39:00.347162+00:00"
|
|||
|
|
model: "Qwen/Qwen3-Coder-Next-FP8"
|
|||
|
|
schema_version: 1
|
|||
|
|
sha256: "f8c9e5793048774d"
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Model
|
|||
|
|
|
|||
|
|
### **Purpose**
|
|||
|
|
This module implements the `ExtraPropertyModel` class, a concrete data model for representing key-value pairs (e.g., ISO channel codes and names or user-defined properties) within a WPF-based UI, conforming to the `IExtraProperty` interface. It supports property change notifications via Prism’s `BasePropertyChanged`, integrates with Prism’s event aggregation system for cross-module communication (e.g., signaling page modifications or paste events), and provides a custom `PasteCommand` to handle clipboard paste operations with special handling for multi-line or multi-field text. Its role is to serve as the view-model backing for UI controls that edit extra properties in ISO data contexts.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### **Public Interface**
|
|||
|
|
|
|||
|
|
#### **`ExtraPropertyModel` class**
|
|||
|
|
- **`public ExtraPropertyModel(IExtraProperty extraProperty)`**
|
|||
|
|
Initializes a new instance by copying `Key` and `Value` from an existing `IExtraProperty` instance. Registers paste commands during construction.
|
|||
|
|
|
|||
|
|
- **`public ExtraPropertyModel()`**
|
|||
|
|
Default constructor. Registers paste commands. `Key` and `Value` are initialized to `null`.
|
|||
|
|
|
|||
|
|
- **`public ExtraPropertyModel(KeyValuePair<string, string> extraProperty)`**
|
|||
|
|
Initializes a new instance using a `KeyValuePair<string, string>`. Registers paste commands.
|
|||
|
|
|
|||
|
|
- **`public UIItemStatus ItemStatus { get; set; }`**
|
|||
|
|
Gets or sets the UI status of the item (e.g., `None`, `Added`, `Modified`, `Deleted`). Backed by `SetProperty` for change notifications.
|
|||
|
|
|
|||
|
|
- **`public string Key { get; set; }`**
|
|||
|
|
Gets or sets the code (e.g., ISO code or user code). Backed by `SetProperty`.
|
|||
|
|
|
|||
|
|
- **`public string Value { get; set; }`**
|
|||
|
|
Gets or sets the associated name (e.g., ISO channel name or user channel name). Backed by `SetProperty`.
|
|||
|
|
|
|||
|
|
- **`public ICommand PasteCommand { get; set; }`**
|
|||
|
|
Exposes the command bound to paste operations. Initialized to a `PasteCommandClass` instance with `PASTE_ID = "ExtraProperty"`.
|
|||
|
|
|
|||
|
|
- **`public const string PASTE_ID = "ExtraProperty"`**
|
|||
|
|
Constant identifier used to distinguish paste operations originating from this model.
|
|||
|
|
|
|||
|
|
#### **`PasteCommandClass` class**
|
|||
|
|
- **`public string Id { get; }`**
|
|||
|
|
Gets the command ID passed during construction (e.g., `"ExtraProperty"`).
|
|||
|
|
|
|||
|
|
- **`public bool CanExecute(object parameter)`**
|
|||
|
|
Always returns `true`.
|
|||
|
|
|
|||
|
|
- **`public void Execute(object parameter)`**
|
|||
|
|
Handles paste logic:
|
|||
|
|
- Validates `parameter` is a `TextBox`.
|
|||
|
|
- Attempts to resolve `IExtraProperty` from `TextBox.DataContext`, falling back to `ChannelCodeBuilder` or `ChannelNameBuilder` contexts.
|
|||
|
|
- Checks clipboard contains text.
|
|||
|
|
- If clipboard text has exactly one line and contains no delimiters (`','`, `';'`, `'\t'`), publishes `PageModifiedEvent` and exits early (single-field paste is handled by `TextChanged`).
|
|||
|
|
- Otherwise, clears `Key`/`Value` on the target `IExtraProperty` (a no-op assignment to trigger change tracking), then publishes `TextPastedEvent` with the raw text, target property, command ID, and `TextBox.Tag`.
|
|||
|
|
- On exception, publishes `PageErrorEvent` with the exception message.
|
|||
|
|
|
|||
|
|
- **`public event EventHandler CanExecuteChanged`**
|
|||
|
|
Required by `ICommand`, but never raised (no-op).
|
|||
|
|
|
|||
|
|
- **`public PasteCommandClass(string id)`**
|
|||
|
|
Constructor storing `id` in `Id`.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### **Invariants**
|
|||
|
|
- `Key` and `Value` may be `null`; no validation is enforced on their values.
|
|||
|
|
- `ItemStatus` defaults to `UIItemStatus.None` and must be explicitly set by consumers.
|
|||
|
|
- The `PasteCommand` is registered globally via `CommandManager.RegisterClassCommandBinding`, meaning it applies to *all* instances of `ExtraPropertyModel` and its subclasses.
|
|||
|
|
- The `Paste` method (private) is never implemented — it is a stub. Actual paste behavior resides entirely in `PasteCommandClass.Execute`.
|
|||
|
|
- `CanExecuteChanged` is never raised by `PasteCommandClass`, so WPF command bindings may not update UI state (e.g., button enablement) dynamically.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### **Dependencies**
|
|||
|
|
- **Imports/Usings**:
|
|||
|
|
- `DTS.Common.ISO.ExtraProperties` → Provides `IExtraProperty` interface.
|
|||
|
|
- `DTS.Common.Controls` → Provides `ChannelCodeBuilder`, `ChannelNameBuilder` types.
|
|||
|
|
- `DTS.Common.Enums` → Provides `UIItemStatus`.
|
|||
|
|
- `DTS.Common.Events` → Provides `PageModifiedEvent`, `TextPastedEvent`, `PageErrorEvent`, and their argument types.
|
|||
|
|
- `Prism.Ioc` → Provides `ContainerLocator` (for resolving `IEventAggregator`).
|
|||
|
|
- `Prism.Events` → Provides `IEventAggregator`.
|
|||
|
|
- **Depended upon**:
|
|||
|
|
- `IExtraProperty` interface (consumed via constructor and paste logic).
|
|||
|
|
- `PageModifiedEvent`, `TextPastedEvent`, `PageErrorEvent` (published by `PasteCommandClass`).
|
|||
|
|
- `ContainerLocator.Container` (runtime dependency for event aggregation).
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### **Gotchas**
|
|||
|
|
- **`Paste` method is empty**: The private `Paste(object sender, ExecutedRoutedEventArgs e)` method is declared but has no implementation; all logic resides in `PasteCommandClass.Execute`. This is likely intentional (to satisfy `CommandBinding` requirements), but may confuse readers.
|
|||
|
|
- **`CanExecuteChanged` is never raised**: `PasteCommandClass` implements `ICommand` but does not notify subscribers of `CanExecute` state changes, potentially causing stale UI (e.g., disabled paste buttons).
|
|||
|
|
- **Ambiguous paste behavior**:
|
|||
|
|
- Single-line, non-delimited text triggers `PageModifiedEvent` but *not* `TextPastedEvent`, while multi-line or delimited text triggers `TextPastedEvent` but *not* `PageModifiedEvent`. This asymmetry may lead to inconsistent state tracking.
|
|||
|
|
- The "wipe out built-in effect" assignment (`extraProperty.Key = extraProperty.Key`) is a no-op and serves no functional purpose beyond triggering change notifications if the property setter is implemented non-trivially elsewhere.
|
|||
|
|
- **Clipboard access without safety checks**: `Clipboard.GetText()` may throw exceptions (e.g., in sandboxed environments), but only generic `Exception` handling is present.
|
|||
|
|
- **No null-safety for `tb.Tag`**: The `tb.Tag` value is passed directly in `TextPastedArgs` without null checks.
|
|||
|
|
- **Tight coupling to Prism**: Reliance on `ContainerLocator.Container` for `IEventAggregator` makes unit testing difficult without Prism infrastructure.
|
|||
|
|
- **No cleanup in constructors**: While the finalizer attempts to null `_key`/`_value`, this is unreliable and unnecessary in modern .NET (where `IDisposable` would be preferred if unmanaged resources were involved — none are evident here).
|