122 lines
9.0 KiB
Markdown
122 lines
9.0 KiB
Markdown
---
|
|
source_files:
|
|
- DataPRO/Modules/ISO/ExtraProperties/ViewModel/ExtraPropertiesListViewModel.cs
|
|
generated_at: "2026-04-16T04:38:41.881863+00:00"
|
|
model: "Qwen/Qwen3-Coder-Next-FP8"
|
|
schema_version: 1
|
|
sha256: "d7dc80e73ad032ff"
|
|
---
|
|
|
|
# ViewModel
|
|
|
|
## **ExtraPropertiesListViewModel Documentation**
|
|
|
|
---
|
|
|
|
### **1. Purpose**
|
|
|
|
`ExtraPropertiesListViewModel` is a Prism-based ViewModel responsible for managing a list of key-value extra properties associated with a data page in the ISO module of the DataPRO application. It provides UI-agnostic data binding, sorting, filtering, clipboard operations (copy/paste), validation, and event-driven integration with the broader application via `IEventAggregator`. It serves as the intermediary between the `IExtraPropertiesListView` UI and the underlying `ExtraPropertyModel` data entities, enabling users to edit, sort, filter, and validate property lists (e.g., metadata, tags, or custom attributes) in a tabular UI.
|
|
|
|
---
|
|
|
|
### **2. Public Interface**
|
|
|
|
All members are defined in `ExtraPropertiesListViewModel`, which implements `IExtraPropertiesListViewModel` (inferred from interface usage). Only explicitly declared public or interface-implementing members are documented.
|
|
|
|
#### **Properties**
|
|
| Property | Type | Description |
|
|
|----------|------|-------------|
|
|
| `View` | `IExtraPropertiesListView` | Reference to the associated view; set externally. |
|
|
| `NotificationRequest` | `InteractionRequest<Notification>` | Prism MVVM Toolkit interaction request for showing non-blocking notifications. |
|
|
| `ConfirmationRequest` | `InteractionRequest<Confirmation>` | Prism MVVM Toolkit interaction request for showing confirmation dialogs. |
|
|
| `IsBusy` | `bool` | Gets/sets busy state; raises `PropertyChanged` for `"IsBusy"`. |
|
|
| `IsMenuIncluded` | `bool` | Gets/sets whether a context menu is included in the view; raises `PropertyChanged` for `"IsMenuIncluded"`. |
|
|
| `IsNavigationIncluded` | `bool` | Gets/sets whether navigation controls are included; raises `PropertyChanged` for `"IsNavigationIncluded"`. |
|
|
| `IsReadOnly` | `bool` | Gets/sets read-only mode (prevents editing); raises `PropertyChanged` for `"IsReadOnly"`. |
|
|
| `AllExtraProperties` | `List<IExtraProperty>` | Full list of all extra properties (including empty trailing row). |
|
|
| `ExtraProperties` | `ObservableCollection<IExtraProperty>` | Filtered/sorted view of `AllExtraProperties`, bound to UI. |
|
|
| `SelectedProperties` | `IExtraProperty[]` | **Throws `NotImplementedException`** — not implemented. |
|
|
| `Page` | `IDataPROPage` | The page this ViewModel is associated with (set via `SetPage`). |
|
|
| `Parent` | `object` | Parent object (set via `SetParent`). |
|
|
| `IsDirty` | `bool` | Declared but never set; always `false`. |
|
|
|
|
#### **Events**
|
|
| Event | Type | Description |
|
|
|-------|------|-------------|
|
|
| `PropertyChanged` | `PropertyChangedEventHandler` | Standard `INotifyPropertyChanged` event; raised via `OnPropertyChanged`. |
|
|
|
|
#### **Methods**
|
|
| Method | Signature | Description |
|
|
|--------|-----------|-------------|
|
|
| `OnPropertyChanged` | `void OnPropertyChanged(string propertyName)` | Raises `PropertyChanged`; if `propertyName == "ExtraProperties"`, publishes `ExtraPropertiesChangedEvent`. |
|
|
| `SetPage` | `void SetPage(IDataPROPage page)` | Sets `Page`. |
|
|
| `SetParent` | `void SetParent(object parent)` | Sets `Parent`. |
|
|
| `Cleanup` | `void Cleanup()` | No-op. |
|
|
| `CleanupAsync` | `Task CleanupAsync()` | Returns `Task.CompletedTask`. |
|
|
| `Initialize` / `InitializeAsync` | Multiple overloads (e.g., `void Initialize()`, `Task InitializeAsync(object parameter)`) | All are no-ops. |
|
|
| `Activated` | `void Activated()` | No-op. |
|
|
| `Filter` | `void Filter(object tag, string term)` | Sets search term for `"Key"` or `"Value"` (via `tag` string) and triggers `Filter()`. **Bug**: `"Value"` case incorrectly sets `_searchTermForField[Fields.Key]`. |
|
|
| `Sort` | `void Sort(object columnTag, bool columnClick)` | Sets sort field (`"Key"` or `"Value"`) and triggers `Sort(...)` + `Filter()`. |
|
|
| `Validate(ref List<string> errors)` | `bool Validate(ref List<string> errors)` | Calls internal `Validate(ref errors, ref warnings)`, returns `true` if no new errors added. |
|
|
| `SetExtraProperties` | `void SetExtraProperties(IList<IExtraProperty> properties)` | Replaces `AllExtraProperties` with copies of input properties, appends a new empty `ExtraPropertyModel`, resets sort/filter, and re-applies. |
|
|
| `CopySelected` | `void CopySelected()` | Copies selected items (`_selectedItems`) into `AllExtraProperties` (just before the trailing empty row), sorts, filters, and publishes `PageModifiedEvent`. |
|
|
| `DeleteSelected` | `void DeleteSelected()` | Removes selected items from both `ExtraProperties` and `AllExtraProperties`; ensures trailing empty row is preserved; publishes `PageModifiedEvent`. |
|
|
|
|
> **Note**: `SelectedProperties` is declared but throws `NotImplementedException`. Its usage is likely incomplete or deprecated.
|
|
|
|
---
|
|
|
|
### **3. Invariants**
|
|
|
|
- **Trailing Empty Row**: `AllExtraProperties` always ends with a single empty `ExtraPropertyModel` instance (key/value both empty/whitespace). This is enforced in:
|
|
- `SetExtraProperties` (adds one after copying input),
|
|
- `MarkModified` (adds one if last item modified),
|
|
- `DeleteSelected` (re-adds one if deleted).
|
|
- **Filtering Logic**: Empty rows (both key and value whitespace) are *always* included in `ExtraProperties` regardless of search term.
|
|
- **Sorting Behavior**: Empty rows are *always* sorted to the *bottom* of `AllExtraProperties` (via `PropertyComparer.Compare`).
|
|
- **Validation Rules**:
|
|
- Duplicate non-empty keys → error.
|
|
- Non-empty keys with empty/whitespace values → warning.
|
|
- **Event Subscription Hack**: `_bAddListeners` static flag ensures only the *second* instantiation of this ViewModel subscribes to `TextPastedEvent`. First instantiation (likely during app startup) skips subscription.
|
|
|
|
---
|
|
|
|
### **4. Dependencies**
|
|
|
|
#### **Imports / Dependencies Used**
|
|
- **Prism Framework**:
|
|
- `Prism.Events.IEventAggregator`, `Prism.Regions.IRegionManager`
|
|
- `Prism.Interactivity.InteractionRequest` (`Notification`, `Confirmation`)
|
|
- **Unity DI Container**: `IUnityContainer`
|
|
- **DataPRO Common Libraries**:
|
|
- `DTS.Common.Events.*` (e.g., `TextPastedEvent`, `PageModifiedEvent`, `PageSelectionChanged`)
|
|
- `DTS.Common.Interface.*` (`IDataPROPage`, `IExtraProperty`, `IExtraPropertiesListView`, `IExtraPropertiesListViewModel`)
|
|
- `DTS.Common.Utilities.NaturalStringComparer` (used in `PropertyComparer`)
|
|
- **Model Layer**:
|
|
- `ExtraProperties.Model.ExtraPropertyModel` (concrete implementation of `IExtraProperty`)
|
|
- **Resources**:
|
|
- `ExtraProperties.Resources.StringResources` (for error/warning messages)
|
|
|
|
#### **Consumers (Inferred)**
|
|
- `ExtraPropertiesListViewModel` is instantiated via Unity DI (due to `[PartCreationPolicy(CreationPolicy.Shared)]` and constructor injection).
|
|
- Likely consumed by `IExtraPropertiesListView` (WPF view) bound to this ViewModel.
|
|
- Subscribes to events published by other modules (e.g., `TextPastedEvent` from clipboard operations).
|
|
- Publishes `PageModifiedEvent`, `ExtraPropertiesChangedEvent`, and `PageSelectionChanged`.
|
|
|
|
---
|
|
|
|
### **5. Gotchas**
|
|
|
|
- **`SelectedProperties` is unimplemented**: Throws `NotImplementedException`. Any code expecting this property will crash.
|
|
- **`Filter` bug**: When filtering by `"Value"`, it incorrectly assigns the term to `_searchTermForField[Fields.Key]` instead of `Fields.Value`.
|
|
- **`_bAddListeners` hack**: Static boolean `_bAddListeners` controls `TextPastedEvent` subscription. First instantiation *does not* subscribe; only the second (and subsequent) do. This is fragile and may break if instantiation order changes.
|
|
- **`IsDirty` never set**: Property is declared but never assigned; always `false`.
|
|
- **`Sort`/`Filter` order**: `Sort` is called *before* `Filter` in `Filter(object, string)` and `Sort(object, bool)`, but `Filter()` is called *after* `Sort(...)` in `Paste`, `CopySelected`, and `DeleteSelected`. This is consistent but non-obvious.
|
|
- **Paste behavior**: `Paste` modifies `ExtraProperties` *in-place* (by index), but `AllExtraProperties` is not updated until `Sort`/`Filter` are called. This may cause inconsistency if accessed mid-operation.
|
|
- **Case sensitivity**: Sorting and filtering use `ToUpper()` + `NaturalStringComparer`, which may not match user expectations for case-insensitive comparisons (e.g., `"a"` and `"A"` sort as equal, but `"ä"` vs `"a"` may behave unexpectedly).
|
|
- **No null checks in `PropertyComparer`**: While `left == right` is handled, `a`/`b` could be `null` after assignment (e.g., if `left`/`right` are non-null but one becomes `null` after `SortAscending` swap logic). `null` checks exist but may not cover all paths.
|
|
- **`MarkModified` side effect**: Appends a new empty row *only* if the modified item is the last in `ExtraProperties`, but uses `ExtraProperties.Last()` — which is the *filtered* list — not `AllExtraProperties`. This may cause inconsistent behavior if filtering is active.
|
|
|
|
---
|
|
|
|
*Documentation generated from `ExtraPropertiesListViewModel.cs` (DataPRO/Modules/ISO/ExtraProperties/ViewModel/ExtraPropertiesListViewModel.cs).* |