From 764a8cffb826a4cebfdddbac868c84e732ea26e8 Mon Sep 17 00:00:00 2001 From: Meik Date: Mon, 9 Feb 2026 21:07:39 +0100 Subject: [PATCH] generic hierarchical control --- .../HierarchicalSelectionControl.xaml | 4 +- .../HierarchicalSelectionControl.xaml.cs | 55 +++++++++---------- 2 files changed, 27 insertions(+), 32 deletions(-) diff --git a/FasdDesktopUi/Basics/UserControls/HierarchicalSelectionControl.xaml b/FasdDesktopUi/Basics/UserControls/HierarchicalSelectionControl.xaml index 2ac439f..35ad628 100644 --- a/FasdDesktopUi/Basics/UserControls/HierarchicalSelectionControl.xaml +++ b/FasdDesktopUi/Basics/UserControls/HierarchicalSelectionControl.xaml @@ -105,12 +105,12 @@ Padding="4" BorderBrush="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}" BorderThickness="1"> - + PreviewMouseWheel="ItemsScrollViewer_PreviewMouseWheel"> VisibleItems => visibleItems; @@ -41,7 +40,6 @@ namespace FasdDesktopUi.Basics.UserControls EnsureTemplateParts(); if (treeViewControl != null) treeViewControl.ItemsSource = VisibleItems; - UpdateDisplaySelection(); } #region DependencyProperties @@ -64,7 +62,6 @@ namespace FasdDesktopUi.Basics.UserControls { control.RebuildLookup(); control.ApplyFilter(control.lastSearchText); - control.TryExpandToSelectedItem(); } } @@ -84,8 +81,8 @@ namespace FasdDesktopUi.Basics.UserControls { if (d is HierarchicalSelectionControl control) { - control.LogSelectedItemChange(e.NewValue as HierarchicalSelectionItem); control.TryExpandToSelectedItem(); + control.SyncTreeSelectionWithSelectedItem(bringIntoView: false); } } @@ -109,6 +106,8 @@ namespace FasdDesktopUi.Basics.UserControls #endregion + #region UI Event Handling + private void ComboBoxControl_DropDownOpened(object sender, EventArgs e) { EnsureTemplateParts(); @@ -116,7 +115,6 @@ namespace FasdDesktopUi.Basics.UserControls searchTextBox?.SelectAll(); suppressTreeSelectionChanged = false; SyncTreeSelectionWithSelectedItem(bringIntoView: true); - LogEntry($"[CategoryPicker] DropDownOpened. Selected={SelectedItem?.FullPath ?? ""}"); DropDownOpened?.Invoke(this, e); } @@ -124,7 +122,6 @@ namespace FasdDesktopUi.Basics.UserControls { searchDelayTimer.Stop(); suppressTreeSelectionChanged = false; - LogEntry("[CategoryPicker] DropDownClosed"); DropDownClosed?.Invoke(this, e); } @@ -138,7 +135,6 @@ namespace FasdDesktopUi.Basics.UserControls { searchDelayTimer.Stop(); lastSearchText = searchTextBox?.Text ?? string.Empty; - LogEntry($"[CategoryPicker] Search text changed: '{lastSearchText}'"); ApplyFilter(lastSearchText); } @@ -153,7 +149,6 @@ namespace FasdDesktopUi.Basics.UserControls if (original != null && !Equals(SelectedItem, original)) { SelectedItem = original; - LogEntry($"[CategoryPicker] Tree selection changed: {original.FullPath}"); } suppressTreeSelectionChanged = true; @@ -161,6 +156,10 @@ namespace FasdDesktopUi.Basics.UserControls } } + #endregion + + #region Data Preparation and Filtering + private HierarchicalSelectionItem ResolveOriginalItem(HierarchicalSelectionItem item) { if (item == null) @@ -222,7 +221,7 @@ namespace FasdDesktopUi.Basics.UserControls clone.SetExpandedRecursive(true); visibleItems.Add(clone); } - + // If the selected item is part of current results, keep it visually selected. SyncTreeSelectionWithSelectedItem(bringIntoView: false); } @@ -243,6 +242,10 @@ namespace FasdDesktopUi.Basics.UserControls } } + #endregion + + #region Tree Selection Sync + private void SyncTreeSelectionWithSelectedItem(bool bringIntoView) { if (SelectedItem == null || string.IsNullOrWhiteSpace(SelectedItem.Id)) @@ -330,6 +333,10 @@ namespace FasdDesktopUi.Basics.UserControls return null; } + #endregion + + #region Template and Scroll Handling + private void EnsureTemplateParts() { if (treeViewControl == null) @@ -349,15 +356,15 @@ namespace FasdDesktopUi.Basics.UserControls searchTextBox.TextChanged += SearchTextBox_TextChanged; } - if (categoryScrollViewer == null) + if (itemsScrollViewer == null) { - categoryScrollViewer = ComboBoxControl.Template.FindName("PART_CategoryScrollViewer", ComboBoxControl) as ScrollViewer; + itemsScrollViewer = ComboBoxControl.Template.FindName("PART_ItemsScrollViewer", ComboBoxControl) as ScrollViewer; } } - private void CategoryScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e) + private void ItemsScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e) { - var scroller = categoryScrollViewer ?? sender as ScrollViewer; + var scroller = itemsScrollViewer ?? sender as ScrollViewer; if (scroller == null || scroller.ScrollableHeight <= 0) return; @@ -392,23 +399,9 @@ namespace FasdDesktopUi.Basics.UserControls e.Handled = true; } - private void UpdateDisplaySelection() - { - // Display handled by template TextBlock bound to SelectedItem.FullPath. - } + #endregion - private void LogSelectedItemChange(HierarchicalSelectionItem newValue) - { - var description = ""; - if (newValue != null) - { - var fullPath = string.IsNullOrWhiteSpace(newValue.FullPath) ? newValue.DisplayName : newValue.FullPath; - var id = string.IsNullOrWhiteSpace(newValue.Id) ? "" : newValue.Id; - description = $"{fullPath} (Id={id})"; - } - - LogEntry($"[CategoryPicker] DependencyProperty SelectedItem updated -> {description}"); - } + #region Keyboard protected override void OnPreviewKeyDown(KeyEventArgs e) { @@ -430,5 +423,7 @@ namespace FasdDesktopUi.Basics.UserControls e.Handled = true; } } + + #endregion } }