Skip to content

Commit 50fa284

Browse files
committed
fixed cell scroll issue when cell width is bigger than TableView
1 parent cc46b21 commit 50fa284

File tree

1 file changed

+30
-23
lines changed

1 file changed

+30
-23
lines changed

src/TableView.cs

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ private void GenerateColumns()
508508
var canFilter = displayAttribute?.GetAutoGenerateFilter() is true or null;
509509
var columnArgs = GenerateColumn(propertyInfo.PropertyType, propertyInfo.Name, header, canFilter);
510510
OnAutoGeneratingColumn(columnArgs);
511-
511+
512512
if (!columnArgs.Cancel && columnArgs.Column is not null)
513513
{
514514
columnArgs.Column.Order = displayAttribute?.GetOrder();
@@ -1132,31 +1132,39 @@ private void InvokeCellSelectionChangedEvent(HashSet<TableViewCellSlot> oldSelec
11321132
/// <param name="slot">The cell slot to scroll into view.</param>
11331133
public async Task<TableViewCell> ScrollCellIntoView(TableViewCellSlot slot)
11341134
{
1135-
if (_scrollViewer is null || !slot.IsValid(this)) return default!;
1135+
if (_scrollViewer is null || !slot.IsValid(this) || await ScrollRowIntoView(slot.Row) is not { } row)
1136+
return default!;
11361137

1137-
var row = await ScrollRowIntoView(slot.Row);
11381138
var (start, end) = GetColumnsInDisplay();
11391139
var xOffset = 0d;
11401140
var yOffset = _scrollViewer.VerticalOffset;
11411141

1142-
if (slot.Column < start)
1142+
// Calculate the left and right edge of the cell
1143+
var cellLeft = Columns.VisibleColumns.Take(slot.Column).Sum(x => x.ActualWidth);
1144+
var cellWidth = Columns.VisibleColumns[slot.Column].ActualWidth;
1145+
var cellRight = cellLeft + cellWidth;
1146+
var viewportLeft = _scrollViewer.HorizontalOffset;
1147+
var viewportRight = viewportLeft + _scrollViewer.ViewportWidth - SelectionIndicatorWidth;
1148+
1149+
// If cell is wider than the viewport, align left edge
1150+
if (cellWidth > _scrollViewer.ViewportWidth - SelectionIndicatorWidth)
11431151
{
1144-
for (var i = 0; i < slot.Column; i++)
1145-
{
1146-
xOffset += Columns.VisibleColumns[i].ActualWidth;
1147-
}
1152+
xOffset = cellLeft;
11481153
}
1149-
else if (slot.Column > end)
1154+
// If cell is left of the viewport, scroll to its left edge
1155+
else if (cellLeft < viewportLeft)
11501156
{
1151-
for (var i = 0; i <= slot.Column; i++)
1152-
{
1153-
xOffset += Columns.VisibleColumns[i].ActualWidth;
1154-
}
1155-
1156-
var change = xOffset - _scrollViewer.HorizontalOffset - (_scrollViewer.ViewportWidth - SelectionIndicatorWidth);
1157-
xOffset = _scrollViewer.HorizontalOffset + change;
1157+
xOffset = cellLeft;
11581158
}
1159-
else if (row is not null)
1159+
// If cell is right of the viewport, scroll so its right edge is visible
1160+
else if (cellRight > viewportRight)
1161+
{
1162+
xOffset = cellRight - (_scrollViewer.ViewportWidth - SelectionIndicatorWidth);
1163+
}
1164+
1165+
// If cell is fully in view, just return
1166+
if ((cellLeft >= viewportLeft && cellRight <= viewportRight) ||
1167+
xOffset == _scrollViewer.HorizontalOffset)
11601168
{
11611169
return row.Cells.ElementAt(slot.Column);
11621170
}
@@ -1176,8 +1184,7 @@ void ViewChanged(object? _, ScrollViewerViewChangedEventArgs e)
11761184
try
11771185
{
11781186
_scrollViewer.ViewChanged += ViewChanged;
1179-
_scrollViewer.ChangeView(xOffset, yOffset, null, true);
1180-
_scrollViewer.ScrollToHorizontalOffset(xOffset);
1187+
_scrollViewer.ChangeView(xOffset, _scrollViewer.VerticalOffset, null, true);
11811188
await tcs.Task;
11821189
}
11831190
finally
@@ -1196,20 +1203,23 @@ void ViewChanged(object? _, ScrollViewerViewChangedEventArgs e)
11961203
{
11971204
if (_scrollViewer is null) return default!;
11981205

1206+
var xOffset = _scrollViewer.HorizontalOffset;
11991207
var item = Items[index];
12001208
index = Items.IndexOf(item); // if the ItemsSource has duplicate items in it. ScrollIntoView will only bring first index of item.
12011209
ScrollIntoView(item);
12021210

12031211
var tries = 0;
12041212
while (tries < 10)
12051213
{
1214+
tries++;
1215+
await Task.Yield();
1216+
12061217
if (ContainerFromIndex(index) is TableViewRow row)
12071218
{
12081219
var transform = row.TransformToVisual(_scrollViewer);
12091220
var positionInScrollViewer = transform.TransformPoint(new Point(0, 0));
12101221
if ((index == 0 && _scrollViewer.VerticalOffset > 0) || (index > 0 && positionInScrollViewer.Y < HeaderRowHeight))
12111222
{
1212-
var xOffset = _scrollViewer.HorizontalOffset;
12131223
var yOffset = index == 0 ? 0d : _scrollViewer.VerticalOffset - row.ActualHeight + positionInScrollViewer.Y + 8;
12141224
var tcs = new TaskCompletionSource<object?>();
12151225

@@ -1237,9 +1247,6 @@ void ViewChanged(object? _, ScrollViewerViewChangedEventArgs e)
12371247

12381248
return row;
12391249
}
1240-
1241-
tries++;
1242-
await Task.Delay(1); // let the animation complete
12431250
}
12441251

12451252
return default;

0 commit comments

Comments
 (0)