Layout rounding can cause DataGrid to hang
- Dominant language
- C#
- Stars
- 7.7k
- Forks
- 1.3k
- Avg merge
- 1d 11h
- Merged PRs (30d)
- 61
Description
### Description
When `UseLayoutRounding=true`, the `DataGrid` can hang in an endless loop trying to get a cell into view after resetting the data then setting `DataGrid.CurrentCell`.
It appears to happen particularly when the column expands beyond the width of the DataGrid, and only on certain screen scales.
### Reproduction Steps
1. Set screen scale to 125% in System > Display Settings
2. Open and run this project: [TestWpfColumnFreeze.zip](https://github.com/user-attachments/files/17346648/TestWpfColumnFreeze.zip)
3. Double click on one of the cells that says "Double click on me"
### Expected behavior
Should not hang at any screen scale or layout rounding setting
### Actual behavior
The application hangs and does not respond to input.
The offending method appears to be in `DataGridCellsPanel.BringIndexIntoView`, where it gets stuck in [this loop](https://github.com/dotnet/wpf/blob/934a82731d7c35d639f221fa818a26ab4518425e/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/DataGridCellsPanel.cs#L2189-L2196):
```c#
while (!IsChildInView(index, out newHorizontalOffset) && !DoubleUtil.AreClose(value, newHorizontalOffset))
{
retryRequested = true;
scrollInfo.SetHorizontalOffset(newHorizontalOffset);
UpdateLayout();
value = newHorizontalOffset;
}
```
Stack Trace:
```
System.Private.CoreLib.dll!System.Threading.Monitor.Enter(object obj, ref bool lockTaken) Unknown
PresentationCore.dll!System.Windows.Media.Visual.GetDpi() Unknown
PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect) Unknown
PresentationFramework.dll!System.Windows.Controls.Primitives.DataGridColumnHeadersPresenter.ArrangeOverride(System.Windows.Size finalSize) Line 168 C#
PresentationFramework.dll!System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect finalRect) Line 3718 C#
PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect) Unknown
PresentationCore.dll!System.Windows.ContextLayoutManager.UpdateLayout() Unknown
> PresentationFramework.dll!System.Windows.Controls.DataGridCellsPanel.BringIndexIntoView(int index) Line 1580 C#
[Native to Managed Transition]
[Managed to Native Transition]
System.Private.CoreLib.dll!System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(object obj, System.Span copyOfArgs, System.Reflection.BindingFlags invokeAttr) Unknown
System.Private.CoreLib.dll!System.Reflection.MethodBaseInvoker.InvokeWithOneArg(object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object[] parameters, System.Globalization.CultureInfo culture) Unknown
System.Private.CoreLib.dll!System.Delegate.DynamicInvokeImpl(object[] args) Unknown
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) Line 83 C#
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object source, System.Delegate callback, object args, int numArgs, System.Delegate catchHandler) Line 24 C#
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeImpl() Line 424 C#
WindowsBase.dll!MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(object obj) Line 99 C#
System.Private.CoreLib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) Unknown
WindowsBase.dll!MS.Internal.CulturePreservingExecutionContext.Run(MS.Internal.CulturePreservingExecutionContext executionContext, System.Threading.ContextCallback callback, object state) Line 85 C#
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.Invoke() Line 350 C#
WindowsBase.dll!System.Windows.Threading.Dispatcher.ProcessQueue() Line 1250 C#
WindowsBase.dll!System.Windows.Threading.Dispatcher.WndProcHook(nint hwnd, int msg, nint wParam, nint lParam, ref bool handled) Line 1367 C#
WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(nint hwnd, int msg, nint wParam, nint lParam, ref bool handled) Line 192 C#
WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o) Line 223 C#
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) Line 73 C#
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object source, System.Delegate callback, object args, int numArgs, System.Delegate catchHandler) Line 24 C#
WindowsBase.dll!System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs) Line 990 C#
WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(nint hwnd, int msg, nint wParam, nint lParam) Line 180 C#
[Native to Managed Transition]
[Managed to Native Transition]
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame) Line 1281 C#
PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore) C#
PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) C#
TestWpfColumnFreeze.dll!TestWpfColumnFreeze.App.Main() Unknown
```
### Regression?
Also happens with latest .NET Framework, not sure about earlier versions.
### Known Workarounds
Turning off layout rounding for the DataGridRow appears to avoid the issue.
### Impact
_No response_
### Configuration
Running on Windows 11 23H2, .NET runtime 8.0.8 or 7.0.0
Reproducible on both x64 and ARM64 architectures.
### Other information
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.