diff --git a/docs/docs/column-sizing.md b/docs/docs/column-sizing.md index d76d1e18..c365b465 100644 --- a/docs/docs/column-sizing.md +++ b/docs/docs/column-sizing.md @@ -109,6 +109,16 @@ Disable resizing for a specific column: Prefer `Preview` if users report a slow or stuttery resize drag on grids with many visible rows; keep the default `Live` if you need cells to reflect the in-progress width at every instant (for example, a template column that reacts to its own width while dragging). +### Star columns while the window resizes + +Star (`*`) columns take the width the other columns leave, so every change in the TableView's width recalculates them, and every realized cell in a star column lays out again. While the user drags the window edge that happens on every frame, which can make resizing stutter on wide or text-heavy tables. [`StarColumnResizeDelay`](xref:WinUI.TableView.TableView.StarColumnResizeDelay) makes star columns wait until the width has stopped changing for that long: + +```xml + +``` + +During the drag, star columns keep their previous width (the table may briefly show a gap or a horizontal scroll bar), then catch up. The first layout and fixed-width columns don't wait. The default, zero, recalculates on every change. + ## Row and header row heights Control row heights with the following `TableView` properties: diff --git a/src/TableView.Properties.cs b/src/TableView.Properties.cs index f99856fa..ddebb7cc 100644 --- a/src/TableView.Properties.cs +++ b/src/TableView.Properties.cs @@ -308,6 +308,11 @@ public partial class TableView /// public static readonly DependencyProperty ShowFilterItemsCountProperty = DependencyProperty.Register(nameof(ShowFilterItemsCount), typeof(bool), typeof(TableView), new PropertyMetadata(false)); + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty StarColumnResizeDelayProperty = DependencyProperty.Register(nameof(StarColumnResizeDelay), typeof(TimeSpan), typeof(TableView), new PropertyMetadata(TimeSpan.Zero)); + /// /// Identifies the dependency property. @@ -412,6 +417,18 @@ public bool ShowFilterItemsCount set => SetValue(ShowFilterItemsCountProperty, value); } + /// + /// Gets or sets how long star-sized columns wait, after the TableView's width stops changing, before they take up + /// the new width. While the window is being resized, recalculating them on every frame re-lays out every realized + /// cell in those columns, which makes resizing stutter on wide or text-heavy tables. Zero (the default) recalculates + /// on every change. + /// + public TimeSpan StarColumnResizeDelay + { + get => (TimeSpan)GetValue(StarColumnResizeDelayProperty); + set => SetValue(StarColumnResizeDelayProperty, value); + } + /// /// Gets or sets a value indicating whether the drag selection rectangle is shown during cell drag selection. /// diff --git a/src/TableViewHeaderRow.cs b/src/TableViewHeaderRow.cs index 3433f324..cc50efb4 100644 --- a/src/TableViewHeaderRow.cs +++ b/src/TableViewHeaderRow.cs @@ -43,6 +43,7 @@ public partial class TableViewHeaderRow : Control private TranslateTransform? _columnDropIndicatorTransform; private Image? _dragHeaderImage; private DispatcherTimer? _desiredWidthTimer; + private DispatcherTimer? _starResizeTimer; private bool _calculatingHeaderWidths; private int _dropColumnIndex; private bool _isValidDropTarget; @@ -760,6 +761,25 @@ public void ClearHeaders() /// private void OnTableViewSizeChanged(object sender, SizeChangedEventArgs e) { + // Resizing a star column re-lays out every realized cell in it, on every frame of a window resize. With a + // delay set, star widths catch up once the resize pauses; the first layout and fixed-width columns don't wait. + if (TableView is { StarColumnResizeDelay: { } delay } && delay > TimeSpan.Zero && e.PreviousSize.Width > 0) + { + _starResizeTimer ??= new DispatcherTimer(); + _starResizeTimer.Interval = delay; + _starResizeTimer.Tick -= OnStarResizeTimerTick; + _starResizeTimer.Tick += OnStarResizeTimerTick; + _starResizeTimer.Stop(); + _starResizeTimer.Start(); + return; + } + + CalculateHeaderWidths(); + } + + private void OnStarResizeTimerTick(object? sender, object e) + { + _starResizeTimer?.Stop(); CalculateHeaderWidths(); }