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.
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 notTextPastedEvent, while multi-line or delimited text triggers TextPastedEvent but notPageModifiedEvent. 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).