Files
2026-04-17 14:55:32 -04:00

5.7 KiB
Raw Permalink Blame History

source_files, generated_at, model, schema_version, sha256
source_files generated_at model schema_version sha256
DataPRO/Modules/Groups/GroupList/View/GroupListView.xaml.cs
2026-04-16T04:47:32.695881+00:00 Qwen/Qwen3-Coder-Next-FP8 1 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 senders 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 models 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.