Files
DP44/enriched-qwen3-coder-next/DataPRO/Modules/ISO/ExtraProperties/Model.md
2026-04-17 14:55:32 -04:00

6.6 KiB
Raw Blame History

source_files, generated_at, model, schema_version, sha256
source_files generated_at model schema_version sha256
DataPRO/Modules/ISO/ExtraProperties/Model/ExtraPropertyModel.cs
2026-04-16T04:39:00.347162+00:00 Qwen/Qwen3-Coder-Next-FP8 1 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 Prisms BasePropertyChanged, integrates with Prisms 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).