71 lines
5.7 KiB
Markdown
71 lines
5.7 KiB
Markdown
|
|
---
|
|||
|
|
source_files:
|
|||
|
|
- DataPRO/Modules/Groups/GroupList/View/GroupListView.xaml.cs
|
|||
|
|
generated_at: "2026-04-16T04:47:32.695881+00:00"
|
|||
|
|
model: "Qwen/Qwen3-Coder-Next-FP8"
|
|||
|
|
schema_version: 1
|
|||
|
|
sha256: "b80e86a41868129e"
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# View
|
|||
|
|
|
|||
|
|
### **Purpose**
|
|||
|
|
This module implements the WPF UI view (`GroupListView`) for displaying a list of groups in a tabular format using a `ListView` with `GridView`. It serves as the concrete implementation of the `IGroupListView` interface, bridging user interactions (sorting, filtering, double-clicking) with the corresponding `IGroupListViewModel` logic. Its role is to render group data and translate UI events into view model commands, adhering to the MVVM pattern.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### **Public Interface**
|
|||
|
|
The class itself is public and implements `IGroupListView` (interface defined elsewhere), but no explicit public methods are declared in this file. All behavior is exposed via event handlers wired in XAML (not shown). The following private methods handle UI events:
|
|||
|
|
|
|||
|
|
- **`ListViewHeader_Click(object sender, RoutedEventArgs e)`**
|
|||
|
|
Handles clicks on standard `GridViewColumnHeader` elements. Extracts the `Tag` (column identifier) and `DataContext` (view model), then invokes `viewModel.Sort(columnTag, true)` to sort ascending.
|
|||
|
|
|
|||
|
|
- **`GridViewColumnHeaderSearchable_OnSearch(object sender, RoutedEventArgs e)`**
|
|||
|
|
Handles search input events on a custom `GridViewColumnHeaderSearchable` control. Extracts the `searchTerm` from `e.OriginalSource` and the `columnTag` from the sender’s `Tag`, then calls `vm.Filter(columnTag, searchTerm)`.
|
|||
|
|
|
|||
|
|
- **`GridViewColumnHeader_OnClick(object sender, RoutedEventArgs e)`**
|
|||
|
|
Handles clicks on `GridViewColumnHeaderSearchable` controls (fallback to standard headers). Attempts to extract `columnTag` from the sender or via `Utils.FindChild`, then calls `vm?.Sort(columnTag, true)`.
|
|||
|
|
|
|||
|
|
- **`MouseDoubleClick(object sender, MouseButtonEventArgs e)`**
|
|||
|
|
Handles double-clicks on the `ListView`. Determines the clicked item index using `GetCurrentIndex`, and if valid, invokes `vm.MouseDoubleClick(index)` on the view model.
|
|||
|
|
|
|||
|
|
- **`GetCurrentIndex(GetPositionDelegate getPosition, ListView lv)`** *(private static)*
|
|||
|
|
Iterates over `ListView` items, checks if the mouse position (via delegate) is within the bounds of each `ListViewItem`, and returns the zero-based index of the first matching item, or `-1` if none.
|
|||
|
|
|
|||
|
|
- **`GetListViewItem(int index, ListView lv)`** *(private static)*
|
|||
|
|
Retrieves the `ListViewItem` container for a given item index using `ItemContainerGenerator.ContainerFromIndex`.
|
|||
|
|
|
|||
|
|
- **`IsMouseOverTarget(Visual target, GetPositionDelegate getPosition)`** *(private static)*
|
|||
|
|
Computes the visual bounds of a `Visual` and checks if the mouse position (from the delegate) lies within those bounds.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### **Invariants**
|
|||
|
|
- The `DataContext` of `GroupListView` **must** be an instance implementing `IGroupListViewModel`; otherwise, casting in event handlers (`(IGroupListViewModel)DataContext`) will fail at runtime.
|
|||
|
|
- Column identifiers (`Tag` properties on `GridViewColumnHeader` or `GridViewColumnHeaderSearchable`) **must** be non-null and consistent with expected keys used by `IGroupListViewModel.Sort` and `IGroupListViewModel.Filter`.
|
|||
|
|
- The `ListView` must contain items compatible with the view model’s data source; `GetCurrentIndex` assumes `lv.Items.Count` is stable during iteration (no concurrent modifications).
|
|||
|
|
- Double-click events only trigger `MouseDoubleClick` on the view model if the mouse is over a valid, generated `ListViewItem`.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### **Dependencies**
|
|||
|
|
**Imports/References (from source):**
|
|||
|
|
- `DTS.Common.Interface.Groups.GroupTemplateList` (namespace, likely contains `IGroupListView` and related interfaces)
|
|||
|
|
- `DTS.Common.Interface.Groups.GroupList` (contains `IGroupListViewModel`)
|
|||
|
|
- `DTS.Common.Controls` (contains `GridViewColumnHeaderSearchable`)
|
|||
|
|
- `DTS.Common.Utils` (contains `Utils.FindChild<T>`)
|
|||
|
|
- Standard WPF namespaces (`System.Windows.*`)
|
|||
|
|
|
|||
|
|
**Depended upon by:**
|
|||
|
|
- XAML file `GroupListView.xaml` (not provided, but implied by `InitializeComponent()` and event bindings).
|
|||
|
|
- Likely consumed by a DI container or view factory that resolves `IGroupListView` and sets its `DataContext` to an `IGroupListViewModel` implementation.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### **Gotchas**
|
|||
|
|
- **Ambiguous event routing**: `ListViewHeader_Click` and `GridViewColumnHeader_OnClick` both handle header clicks but for different header types. If a `GridViewColumnHeaderSearchable` is clicked, `GridViewColumnHeader_OnClick` runs, but `ListViewHeader_Click` may also fire depending on XAML event wiring—risk of duplicate sorting/filtering if not coordinated.
|
|||
|
|
- **Unsafe cast in `ListViewHeader_Click`**: Assumes `colHeader.DataContext` is `IGroupListViewModel`; if the view is reused or bound incorrectly, this throws `InvalidCastException`.
|
|||
|
|
- **Fallback logic in `GridViewColumnHeader_OnClick`**: Uses `Utils.FindChild<GridViewColumnHeaderSearchable>` to extract `Tag` if the sender is not already a `GridViewColumnHeaderSearchable`. This implies tight coupling to a specific visual tree structure and may break if the control template changes.
|
|||
|
|
- **Mouse position calculation**: `GetCurrentIndex` uses `VisualTreeHelper.GetDescendantBounds`, which may be expensive or inaccurate if items are virtualized (e.g., with `VirtualizingStackPanel`).
|
|||
|
|
- **No null-safety for `vm`**: In `MouseDoubleClick`, `vm?.Sort(...)` uses null-conditional, but `vm.MouseDoubleClick(index)` does not—risk of `NullReferenceException` if `DataContext` is unset.
|
|||
|
|
- **Search term source**: `GridViewColumnHeaderSearchable_OnSearch` casts `e.OriginalSource` to `string` for `searchTerm`, implying the event args’ `OriginalSource` *is* the search string—this is non-standard and highly dependent on how `GridViewColumnHeaderSearchable` raises the event.
|