Skip to content

Commit 3ea4428

Browse files
committed
Fixing bug in OverrideMetadata and improving perf
1 parent f473b1d commit 3ea4428

15 files changed

Lines changed: 443 additions & 93 deletions

DaxStudio.Controls.Example/QueryPlanTreeExample.xaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@
116116

117117
<!-- Tree Column using custom control -->
118118
<ctrl:TreeColumn Header="Operation"
119-
Width="*"
119+
Width="Auto"
120+
MinWidth="900"
120121
TextPath="Data.Operation"
121122
IndentWidth="16"
122123
ExpanderTemplate="{StaticResource SnoopExpanderTemplate}"

DaxStudio.Controls.Example/QueryPlanTreeExampleViewModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class QueryPlanTreeExampleViewModel : PropertyChangedBase
1616
public QueryPlanTreeExampleViewModel()
1717
{
1818
var filePath = @"..\..\..\data\QueryPlan.json";
19-
filePath = @"c:\temp\QueryPlan.json";
19+
//filePath = @"c:\temp\QueryPlan.json";
2020
if (File.Exists(filePath))
2121
{
2222
try

DaxStudio.Controls.Example/TreeGridExample.xaml

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<UserControl.Resources>
88
<ResourceDictionary>
99
<SolidColorBrush x:Key="TextBrush" Color="Blue"/>
10-
<SolidColorBrush x:Key="LineBrush" Color="HotPink"/>
10+
<SolidColorBrush x:Key="LineBrush" Color="LimeGreen"/>
1111

1212
<ControlTemplate x:Key="Expander2" TargetType="ToggleButton">
1313
<Border Background="Transparent"
@@ -66,16 +66,26 @@
6666
</ControlTemplate.Triggers>
6767
</ControlTemplate>
6868

69-
<Style x:Key="LineStyle" TargetType="{x:Type ctrl:TreeCell}">
70-
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
69+
<Style x:Key="MyCellStyle" TargetType="{x:Type ctrl:TreeCell}" BasedOn="{StaticResource {x:Type ctrl:TreeCell}}">
70+
<Setter Property="Foreground" Value="Navy"/>
7171
<Setter Property="TextForeground" Value="{DynamicResource LineBrush}"/>
7272
<Setter Property="LineStroke" Value="{DynamicResource LineBrush}"/>
73-
<Setter Property="SelectedLineStroke" Value="Cyan"/>
73+
<Setter Property="SelectedLineStroke" Value="HotPink"/>
74+
<Setter Property="IndentWidth" Value="20"/>
75+
<Setter Property="LineThickness" Value="1"/>
76+
<!--<Setter Property="FontWeight" Value="Bold"/>-->
77+
<Style.Triggers>
78+
<DataTrigger Binding="{Binding Data.Name}" Value="ProductID">
79+
<Setter Property="FontWeight" Value="Black"/>
80+
</DataTrigger>
81+
</Style.Triggers>
7482
</Style>
7583

76-
<Style TargetType="{x:Type ctrl:TreeLine}">
77-
84+
<Style x:Key="MyTextStyle" TargetType="TextBlock">
85+
<Setter Property="FontWeight" Value="Bold"/>
86+
<Setter Property="FontStyle" Value="Italic"/>
7887
</Style>
88+
7989
<!--<Color x:Key="DaxStudio.TreeGrid.Colors.ExpanderPath">#FF00FF00</Color>
8090
<SolidColorBrush x:Key="DaxStudio.TreeGrid.Brushes.ExpanderPath" Color="{StaticResource DaxStudio.TreeGrid.Colors.ExpanderPath}"/>-->
8191
</ResourceDictionary>
@@ -100,11 +110,11 @@
100110

101111
<!-- Hierarchical Data Grid -->
102112
<ctrl:TreeGrid x:Name="HierarchicalGrid"
103-
Grid.Row="1"
104-
RootItems="{Binding RootItems}"
105-
ChildrenBindingPath="Children"
113+
Grid.Row="1"
114+
RootItems="{Binding RootItems}"
115+
ChildrenBindingPath="Children"
106116
IsReadOnly="False"
107-
Margin="5">
117+
Margin="5">
108118

109119
<!-- Define columns -->
110120
<ctrl:TreeGrid.Columns>
@@ -124,16 +134,23 @@
124134
</DataGridTextColumn>
125135
<!-- Tree Column using custom control -->
126136
<ctrl:TreeColumn Header="Name"
127-
Width="300"
128-
TextPath ="Data.Name"
129-
IndentWidth="16"
130-
TreeLineStyle="{StaticResource LineStyle}"
131-
LineThickness="1"
132-
133-
ShowTreeLines="{Binding DataContext.ShowExpanders, RelativeSource={RelativeSource AncestorType={x:Type ctrl:TreeGrid}}}"
134-
ShowExpander="{Binding DataContext.ShowExpanders, RelativeSource={RelativeSource AncestorType={x:Type ctrl:TreeGrid}}}"
135-
>
136-
137+
Width="300"
138+
TextPath ="Data.Name"
139+
IndentWidth="16"
140+
TextStyle="{StaticResource MyTextStyle}"
141+
TreeCellStyle="{StaticResource MyCellStyle}"
142+
ShowTreeLines="{Binding DataContext.ShowExpanders, RelativeSource={RelativeSource AncestorType={x:Type ctrl:TreeGrid}}}"
143+
ShowExpander="{Binding DataContext.ShowExpanders, RelativeSource={RelativeSource AncestorType={x:Type ctrl:TreeGrid}}}"
144+
>
145+
146+
<!--<ctrl:TreeColumn.TextTemplate>
147+
<DataTemplate>
148+
<TextBlock Text="{Binding .}"
149+
Foreground="{DynamicResource TextBrush}"
150+
FontStyle="Italic"
151+
/>
152+
</DataTemplate>
153+
</ctrl:TreeColumn.TextTemplate>-->
137154
</ctrl:TreeColumn>
138155

139156
<DataGridTextColumn Header="Description"

DaxStudio.Controls/Controls/TreeGrid/GenericTreeGrid.cs

Lines changed: 96 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)