microsoft / microsoft/microsoft-ui-xaml
ListView with non-virtualizing ItemsPanel mishandles multi-item CollectionChanged and later crashes
- Dominant language
- C++
- Stars
- 8.4k
- Forks
- 942
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 105
Description
### Describe the bug
When a collection raises a valid multi-item NotifyCollectionChangedAction.Add notification, a bound WinUI 3 ListView using a StackPanel as its ItemsPanel processes only one insertion.
The source collection contains four items, but the ListView displays only the first. A subsequent removal at index 1 throws E_INVALIDARG because the ListView and source collection have become desynchronized.
The notification includes multiple NewItems and a valid NewStartingIndex of 0. Using the ListView's default ItemsPanel works correctly.
### Why is this important?
The range addition silently leaves the UI inconsistent with its source collection. A later, otherwise valid collection removal can then terminate the application with an unhandled E_INVALIDARG.
Range-capable observable collections are commonly used to reduce notification and layout overhead. The initial problem can also be difficult to diagnose because the crash happens during a later collection operation.
### Steps to reproduce the bug
1. Build and run the attached minimal project: [WinUIRangeCollectionChanged.zip](https://github.com/user-attachments/files/30167488/WinUIRangeCollectionChanged.zip)
2. Click "1. Add four items".
3. Observe that the source count is 4, but the ListView displays only "one".
4. Click "2. Remove item at index 1".
5. The application crashes with E_INVALIDARG.
The collection raises this notification:
```
OnCollectionChanged(new NotifyCollectionChangedEventArgs(
NotifyCollectionChangedAction.Add,
(IList)items,
index));
```
### Actual behavior
After the multi-item Add notification, the source collection contains four items but the ListView displays only the first item.
Removing the source item at index 1 then throws:
```
System.ArgumentException: The parameter is incorrect. (0x80070057)
at WinRT.ExceptionHelpers.g__Throw|41_0(Int32)
at ABI.System.Collections.Specialized.NotifyCollectionChangedEventHandler.NativeDelegateWrapper.Invoke(Object, NotifyCollectionChangedEventArgs)
at System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs)
at System.Collections.ObjectModel.ObservableCollection`1.RemoveItem(Int32)
```
### Expected behavior
The ListView should process every item contained in NewItems, display all four items, and remain synchronized with the source collection so that the later removal succeeds.
### Screenshots
_No response_
### NuGet package version
Microsoft.WindowsAppSDK.WinUI 2.3.0
### Windows version
Windows 11 (25H2): Build 26200
### Additional context
Reproduced with:
- Windows 11 25H2, build 26200.8894
- .NET 10.0.9
- Microsoft.WindowsAppSDK.WinUI 2.3.0
- Microsoft.WindowsAppSDK.Runtime 2.3.1
- Microsoft.WindowsAppSDK.Foundation 2.3.5
- Microsoft.WindowsAppSDK.InteractiveExperiences 2.1.3
- Microsoft.Windows.CsWinRT 2.3.0-prerelease.251115.2
- Unpackaged x64 application
The problem occurs when ListView uses a non-virtualizing StackPanel as its ItemsPanel. Using the default ItemsPanel works correctly.
Workarounds are to raise one Add notification per item or to raise NotifyCollectionChangedAction.Reset.
Related issues:
https://github.com/microsoft/microsoft-ui-xaml/issues/7993
https://github.com/dotnet/runtime/issues/18087
The Add handling appears to forward one ItemInserted notification without accounting for NewItems.Count:
https://github.com/microsoft/microsoft-ui-xaml/blob/main/dxaml/xcp/dxaml/lib/BindableObservableVectorWrapper.cpp#L198-L228
Contributor guide
Research direction
Start with dxaml/xcp/dxaml/lib/BindableObservableVectorWrapper.cpp at lines 198-228 and reproduce the attached project using a StackPanel ItemsPanel and a multi-item Add notification. Trace how NewItems and NewStartingIndex are handled, then verify that all four items appear and the later removal at index 1 succeeds without E_INVALIDARG.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- desktop
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 58/100