--- source_files: - DataPRO/Modules/ISO/ExtraProperties/View/ExtraPropertiesListView.xaml.cs generated_at: "2026-04-16T04:39:06.939358+00:00" model: "Qwen/Qwen3-Coder-Next-FP8" schema_version: 1 sha256: "35a6fb72ede64411" --- # View ## Documentation: `ExtraPropertiesListView` Module --- ### **1. Purpose** `ExtraPropertiesListView` is a WPF user control implementing the `IExtraPropertiesListView` interface to render and interact with a list of extra properties (key-value pairs) in the ISO module. It serves as the view layer in a MVVM pattern, handling UI events (sorting, filtering, selection, editing) and delegating logic to its bound `IExtraPropertiesListViewModel`. The control supports interactive column sorting (via header clicks or text clicks), filtering by column tag, real-time validation and modification tracking during inline editing of property keys and values, and selection synchronization with the view model. --- ### **2. Public Interface** The class itself is `public partial class ExtraPropertiesListView : IExtraPropertiesListView`. It exposes no *public* methods or properties beyond those defined by the interface `IExtraPropertiesListView` (not shown in source), but its *event handlers* are the primary public-facing behavior surface. All handlers are private `RoutedEventHandler` or `KeyEventHandler` methods wired via XAML (not visible here, but implied by naming and usage). | Member | Signature | Behavior | |--------|-----------|----------| | `ExtraPropertiesListView()` | `public ExtraPropertiesListView()` | Constructor; calls `InitializeComponent()` to load the associated XAML. | | `GridViewColumnHeaderSearchable_OnSearch` | `private void GridViewColumnHeaderSearchable_OnSearch(object sender, RoutedEventArgs e)` | Extracts `searchTerm` from `e.OriginalSource` and `columnTag` from the `Tag` of the `GridViewColumnHeaderSearchable` sender, then invokes `viewModel.Filter(columnTag, searchTerm)`. | | `GridViewColumnHeader_OnClick` | `private void GridViewColumnHeader_OnClick(object sender, RoutedEventArgs e)` | Extracts `columnTag` from the `Tag` of the `GridViewColumnHeaderSearchable` sender (or via `Utils.FindChild`), then invokes `vm?.Sort(columnTag, true)`. | | `ExtraPropertyKeyTextBox_KeyDown` | `private void ExtraPropertyKeyTextBox_KeyDown(object sender, KeyEventArgs e)` | If `DataContext` is `ExtraPropertiesListViewModel` and the `TextBox`’s `DataContext` is `IExtraProperty`, calls `vm.MarkModified(iep)`. | | `ExtraPropertyKeyTextBox_TextChanged` | `private void ExtraPropertyKeyTextBox_TextChanged(object sender, TextChangedEventArgs e)` | Same context checks as above; calls `vm.MarkModified(iep)` and then `vm.Validate(ref notUsed1, ref notUsed2)` (with unused `List` parameters). | | `ExtraPropertyValueTextBox_KeyDown` | `private void ExtraPropertyValueTextBox_KeyDown(object sender, KeyEventArgs e)` | Same as `ExtraPropertyKeyTextBox_KeyDown`; calls `vm.MarkModified(iep)`. | | `ExtraPropertyValueTextBox_TextChanged` | `private void ExtraPropertyValueTextBox_TextChanged(object sender, TextChangedEventArgs e)` | Same as `ExtraPropertyKeyTextBox_TextChanged`; calls `vm.MarkModified(iep)` and `vm.Validate(...)`. | | `ExtraProperties_SelectionChanged` | `private void ExtraProperties_SelectionChanged(object sender, SelectionChangedEventArgs e)` | Collects selected `IExtraProperty` items from the `ListView`, then calls `vm.SetSelection(...)` with the array. | | `ExtraPropertiesListView_PreviewMouseLeftButtonUp` | `private void ExtraPropertiesListView_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)` | Performs hit-testing to detect clicks on column headers (`TextBlock`, `KeyColumnHeader`, or `ValueColumnHeader`) or descendants; if detected, calls `vm?.Sort(tag, true)` for the corresponding column. Also returns early if the click is on a `ScrollViewer`. | > **Note**: Column header tags (`KeyColumnHeader.Tag`, `ValueColumnHeader.Tag`) are used as sort keys. Their values are assumed to be strings (e.g., `"Key"`, `"Value"`), inferred from usage in `PreviewMouseLeftButtonUp`. --- ### **3. Invariants** - **DataContext Contract**: The `DataContext` must implement `IExtraPropertiesListViewModel` (or be `ExtraPropertiesListViewModel`, a concrete implementation). All event handlers cast `DataContext` to this interface or concrete type before use. - **Item Type Contract**: Selected items in the `ListView` and `TextBox.DataContext` items must be of type `IExtraProperty`. Non-conforming items are silently skipped in `ExtraProperties_SelectionChanged`. - **Validation Side Effect**: Every `TextChanged` event on key/value `TextBox`es triggers `vm.Validate(...)`, regardless of whether the text actually changed meaningfully. - **Sorting Trigger**: Sorting is *always* invoked with `ascending: true` (hardcoded), regardless of previous sort state or direction. - **Hit-Test Robustness**: The `PreviewMouseLeftButtonUp` handler performs multiple hit-tests (visual tree + input hit-test) to reliably detect clicks on headers despite nested visual elements (e.g., `Border`, `Rectangle`). --- ### **4. Dependencies** #### **External Dependencies (from imports)**: - `System.Collections.Generic`, `System.Windows.*`: Standard WPF and .NET types. - `DTS.Common.Controls`: Contains `GridViewColumnHeaderSearchable` (custom control used for searchable column headers). - `DTS.Common.Interface.ISO.ExtraProperties`: Defines `IExtraPropertiesListView`, `IExtraPropertiesListViewModel`, and `IExtraProperty`. - `DTS.Common.Utils`: Provides `Utils.FindChild` (used in `GridViewColumnHeader_OnClick` to locate `Tag` from nested elements). #### **Internal Dependencies**: - `ExtraProperties.Resources.StringResources`: Used for localized strings `"Key"` and `"Value"` (in `PreviewMouseLeftButtonUp`). - `ExtraPropertiesListView.xaml`: The associated XAML file (not shown), which defines `ExtraPropertiesListViewLV`, `KeyColumnHeader`, `ValueColumnHeader`, and event bindings. #### **Depended Upon By**: - The module likely binds this view to an `ExtraPropertiesListViewModel` instance (or similar) via `DataContext`. No direct callers are visible, but the interface `IExtraPropertiesListView` implies integration into a larger ISO module UI. --- ### **5. Gotchas** - **Unused `Validate` Parameters**: Both `TextChanged` handlers call `vm.Validate(ref notUsed1, ref notUsed2)` with newly allocated, unused `List` variables. This suggests either incomplete validation reporting or legacy code where validation errors are ignored by the view. - **Hardcoded Sort Direction**: `vm.Sort(..., true)` is called unconditionally with `ascending: true`. No logic exists to toggle sort direction (e.g., on repeated clicks), which may confuse users expecting standard UI behavior. - **Redundant Hit-Testing**: The `PreviewMouseLeftButtonUp` handler performs two hit-tests (`VisualTreeHelper.HitTest` and `InputHitTest`) and checks multiple element types (`TextBlock`, `UIElement`, `ScrollViewer`, `KeyColumnHeader`, `ValueColumnHeader`). This complexity hints at prior instability in click detection. - **Assumed `Tag` Type**: `columnTag` is used directly as a sort key in `vm.Sort(columnTag, ...)`. Its type is inferred from usage (likely `string`), but not enforced or documented in the source. - **No Null Safety for `vm`**: Multiple calls use `vm?.Sort(...)` or `vm?.Filter(...)`, but `vm.MarkModified(...)` and `vm.SetSelection(...)` do *not* use null-conditional operators. If `DataContext` is null or wrong type, these will throw. - **`KeyDown` vs `TextChanged` Duplication**: Both `KeyDown` and `TextChanged` handlers call `MarkModified` and `Validate`. This may cause redundant work or validation flicker if both events fire for a single edit (e.g., typing + Enter). > **None identified from source alone.** *(Note: While several potential issues are noted above, they are inferred from code structure and behavior—not documented quirks.)*