@@ -39,6 +39,9 @@ public class GenericTreeGrid<T> : DataGrid where T : class
3939 private DispatcherTimer _refreshTimer ;
4040 private const int REFRESH_DEBOUNCE_MS = 20 ; // Debounce delay
4141
42+ // Flag to suppress selection changed events during collapse
43+ private bool _suppressSelectionChanged = false ;
44+
4245 public ICommand ExecuteCustomDescendantFilter { get ; private set ; }
4346 // Add these fields to track bound collections
4447 private INotifyCollectionChanged _rootItemsCollectionNotifier ;
@@ -61,6 +64,11 @@ public GenericTreeGrid()
6164 this . HeadersVisibility = DataGridHeadersVisibility . Column ;
6265 this . GridLinesVisibility = DataGridGridLinesVisibility . None ;
6366 this . IsReadOnly = true ;
67+
68+ // Explicitly set scroll bar visibility
69+ this . HorizontalScrollBarVisibility = ScrollBarVisibility . Auto ;
70+ this . VerticalScrollBarVisibility = ScrollBarVisibility . Auto ;
71+
6472 // Use recycling mode for even better performance
6573 VirtualizingPanel . SetVirtualizationMode ( this , VirtualizationMode . Recycling ) ;
6674 VirtualizingPanel . SetScrollUnit ( this , ScrollUnit . Item ) ;
@@ -463,13 +471,23 @@ private void CollapseItemRecursively(TreeGridRow<T> row)
463471
464472 using ( new OverrideCursor ( Cursors . Wait ) )
465473 {
474+ // Suppress TreeLine redraws FIRST before any other operations
475+ TreeLine . SuppressRedraws ( true ) ;
476+
466477 _isInBulkOperation = true ;
467478 _isUpdatingFlattenedRows = true ;
479+ _suppressSelectionChanged = true ; // Suppress selection changed during collapse
468480
469481 try
470482 {
471483 using ( new TreeGridFocusManager < T > ( this ) )
472484 {
485+ // Clear all selection line highlights before collapse to prevent unnecessary redraws
486+ if ( SelectedItem is TreeGridRow < T > selectedRow )
487+ {
488+ ClearSelectedLineRecursive ( selectedRow ) ;
489+ }
490+
473491 // First collect all rows that will be affected
474492 var rowsToCollapse = new HashSet < TreeGridRow < T > > ( ) ;
475493 CollectRowsToCollapseRecursively ( row , rowsToCollapse ) ;
@@ -509,8 +527,12 @@ private void CollapseItemRecursively(TreeGridRow<T> row)
509527 }
510528 finally
511529 {
530+ // Re-enable TreeLine redraws
531+ TreeLine . SuppressRedraws ( false ) ;
532+
512533 _isUpdatingFlattenedRows = false ;
513534 _isInBulkOperation = false ;
535+ _suppressSelectionChanged = false ; // Re-enable selection changed
514536 }
515537 }
516538 }
@@ -536,20 +558,41 @@ private void CollectRowsToCollapseRecursively(TreeGridRow<T> row, HashSet<TreeGr
536558 // Modify the OnRowIsExpandedChanged method to handle recursive operations
537559 private void OnRowIsExpandedChanged ( TreeGridRow < T > row )
538560 {
539-
540-
541561 // Skip during bulk operations to avoid triggering multiple refreshes
542562 if ( _isInBulkOperation )
543563 return ;
544564
545565 Debug . WriteLine ( $ "OnRowIsExpandedChanged: Row at level { row . Level } changed to expanded={ row . IsExpanded } ") ;
546566
547- // Refresh the data to update UI
548- RefreshData ( ) ;
567+ // If this is a user-initiated collapse, suppress redraws during the operation
568+ bool isUserCollapse = row . _isCollapsing ;
549569
550- if ( row . IsExpanded )
570+ if ( isUserCollapse )
571+ {
572+ Debug . WriteLine ( $ "OnRowIsExpandedChanged: SUPPRESSING redraws for user-initiated collapse at Level={ row . Level } ") ;
573+ TreeLine . SuppressRedraws ( true ) ;
574+ }
575+
576+ try
577+ {
578+ // Refresh the data to update UI (this is debounced)
579+ DebounceService . Debounce ( DoRefreshData , TimeSpan . FromMilliseconds ( REFRESH_DEBOUNCE_MS ) ) ;
580+
581+ if ( row . IsExpanded )
582+ {
583+ SetSelectedLineRecursive ( row , row . Level , true ) ;
584+ }
585+ }
586+ finally
551587 {
552- SetSelectedLineRecursive ( row , row . Level , true ) ;
588+ // IMPORTANT: Re-enable redraws IMMEDIATELY after scheduling the debounced refresh
589+ // This ensures suppression doesn't stay on if multiple rapid operations occur
590+ if ( isUserCollapse )
591+ {
592+ Debug . WriteLine ( "OnRowIsExpandedChanged: Re-enabling redraws after scheduling refresh" ) ;
593+ TreeLine . SuppressRedraws ( false ) ;
594+ row . _isCollapsing = false ;
595+ }
553596 }
554597 }
555598
@@ -975,12 +1018,12 @@ protected override void OnContextMenuOpening(ContextMenuEventArgs e)
9751018 private void OnSelectionChanged ( object sender , SelectionChangedEventArgs e )
9761019 {
9771020 Debug . WriteLine ( $ "OnSelectionChanged: Entry - Added={ e . AddedItems . Count } , Removed={ e . RemovedItems . Count } ") ;
978- Debug . WriteLine ( $ "OnSelectionChanged: _isUpdatingFlattenedRows={ _isUpdatingFlattenedRows } ") ;
1021+ Debug . WriteLine ( $ "OnSelectionChanged: _isUpdatingFlattenedRows={ _isUpdatingFlattenedRows } , _suppressSelectionChanged= { _suppressSelectionChanged } ") ;
9791022
980- // Skip if called during collection update
981- if ( _isUpdatingFlattenedRows )
1023+ // Skip if called during collection update or if suppressed
1024+ if ( _isUpdatingFlattenedRows || _suppressSelectionChanged )
9821025 {
983- Debug . WriteLine ( "OnSelectionChanged: Skipping during collection update" ) ;
1026+ Debug . WriteLine ( "OnSelectionChanged: Skipping during collection update or suppressed " ) ;
9841027 return ;
9851028 }
9861029
@@ -1017,10 +1060,16 @@ private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
10171060
10181061 private static void ClearSelectedLineRecursive ( TreeGridRow < T > row )
10191062 {
1063+ Debug . WriteLine ( $ "[GenericTreeGrid] ClearSelectedLineRecursive: Level={ row . Level } , Suppressed={ TreeGridRenderSuppressionHelper . IsRenderingSuppressed } ") ;
1064+
10201065 if ( row . SelectedLineLevels != null )
10211066 {
10221067 for ( int i = 0 ; i < row . SelectedLineLevels . Count ; i ++ )
10231068 {
1069+ if ( row . SelectedLineLevels [ i ] ) // Only log actual changes
1070+ {
1071+ Debug . WriteLine ( $ "[GenericTreeGrid] ClearSelectedLineRecursive: Clearing level { i } ") ;
1072+ }
10241073 row . SelectedLineLevels [ i ] = false ;
10251074 }
10261075 }
@@ -1056,7 +1105,14 @@ internal void ToggleItem(T item)
10561105 {
10571106 if ( _itemToRowMap . TryGetValue ( item , out var row ) )
10581107 {
1059- row . _isCollapsing = row . IsExpanded ;
1108+ // If collapsing, suppress redraws immediately
1109+ if ( row . IsExpanded )
1110+ {
1111+ Debug . WriteLine ( "ToggleItem: Suppressing redraws for collapse" ) ;
1112+ TreeLine . SuppressRedraws ( true ) ;
1113+ row . _isCollapsing = true ;
1114+ }
1115+
10601116 row . IsExpanded = ! row . IsExpanded ;
10611117 RefreshData ( ) ;
10621118
@@ -1122,11 +1178,21 @@ public void CollapseAll()
11221178 {
11231179 using ( new OverrideCursor ( Cursors . Wait ) )
11241180 {
1181+ // Suppress TreeLine redraws FIRST before any other operations
1182+ TreeLine . SuppressRedraws ( true ) ;
1183+
11251184 _isInBulkOperation = true ;
11261185 _isUpdatingFlattenedRows = true ;
1186+ _suppressSelectionChanged = true ; // Suppress selection changed during collapse all
11271187
11281188 try
11291189 {
1190+ // Clear all selection line highlights before collapse to prevent unnecessary redraws
1191+ if ( SelectedItem is TreeGridRow < T > selectedRow )
1192+ {
1193+ ClearSelectedLineRecursive ( selectedRow ) ;
1194+ }
1195+
11301196 // Mark all rows as collapsed
11311197 foreach ( var row in _itemToRowMap . Values )
11321198 {
@@ -1155,8 +1221,12 @@ public void CollapseAll()
11551221 }
11561222 finally
11571223 {
1224+ // Re-enable TreeLine redraws
1225+ TreeLine . SuppressRedraws ( false ) ;
1226+
11581227 _isUpdatingFlattenedRows = false ;
11591228 _isInBulkOperation = false ;
1229+ _suppressSelectionChanged = false ; // Re-enable selection changed
11601230 }
11611231 }
11621232 }
@@ -1313,6 +1383,21 @@ private DataTemplate CreateDefaultCellTemplate()
13131383
13141384 private void Expander_PreviewMouseDown ( object sender , MouseButtonEventArgs e )
13151385 {
1386+ // Check if this is a collapse operation and suppress redraws
1387+ if ( sender is CheckBox checkBox && checkBox . DataContext is TreeGridRow < T > row )
1388+ {
1389+ if ( row . IsExpanded )
1390+ {
1391+ Debug . WriteLine ( $ "[GenericTreeGrid] Expander_PreviewMouseDown: SUPPRESSING redraws for collapse at Level={ row . Level } ") ;
1392+ TreeLine . SuppressRedraws ( true ) ;
1393+ row . _isCollapsing = true ;
1394+ }
1395+ else
1396+ {
1397+ Debug . WriteLine ( $ "[GenericTreeGrid] Expander_PreviewMouseDown: Expanding at Level={ row . Level } ") ;
1398+ }
1399+ }
1400+
13161401 e . Handled = true ;
13171402 }
13181403
0 commit comments