Open
Description
Description
Crash happens if you put VirtualizingStackPanel inside any VirtualizingPanel, e.g. VirtualizingStackPanel.
Reproduction Steps
Put ItemsControl with VirtualizingStackPanel iside other VirtualizingStackPanel and add new Item to it at runtime.
<VirtualizingStackPanel>
<ItemsControl x:Name="ItemsControl">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<Button Content="AddItem" Click="OnButtonClick"/>
</VirtualizingStackPanel>
Code behind is:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ItemsControl.ItemsSource = Items;
}
private void OnButtonClick(object sender, RoutedEventArgs e) => Items.Insert(0,"Hello World");
public ObservableCollection<string> Items { get; } = new ();
}
The problem could be reproduced on .net6-9. I haven't tested earlier versions though.
Crash happens inside VirtualizingStackPanel.cs
protected override bool ShouldItemsChangeAffectLayoutCore(bool areItemChangesLocal, ItemsChangedEventArgs args)
{
\\...
if (IsScrolling)
{
flag = !IsExtendedViewportFull();
if (!flag)
{
UpdateExtent(areItemChangesLocal);
}
}
else
{
DependencyObject itemsOwnerInternal = ItemsControl.GetItemsOwnerInternal(this);
if (VisualTreeHelper.GetParent(itemsOwnerInternal) is VirtualizingPanel virtualizingPanel)
{
UpdateExtent(areItemChangesLocal);
IItemContainerGenerator itemContainerGenerator = virtualizingPanel.ItemContainerGenerator;
// Here itemContainerGenerator is null, but is not checked for null, as a result NullReferenceException is thrown
int itemIndex = ((ItemContainerGenerator)itemContainerGenerator).IndexFromContainer(itemsOwnerInternal, returnLocalIndex: true);
ItemsChangedEventArgs args2 = new ItemsChangedEventArgs(NotifyCollectionChangedAction.Reset, itemContainerGenerator.GeneratorPositionFromIndex(itemIndex), 1, 1);
flag = virtualizingPanel.ShouldItemsChangeAffectLayout(areItemChangesLocal: false, args2);
}
else
{
flag = true;
}
}
}
Expected behavior
No Exception is thrown
Actual behavior
Exception is thrown.
Regression?
It seems it worked on .net framework 4.8, but doesn't work for .net6-9.
Known Workarounds
Put non-virtualizing panel in-between ItemsControl and VirtualizingStackPanel:
<VirtualizingStackPanel>
<Grid>
<ItemsControl x:Name="ItemsControl">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
<Button Content="AddItem" Click="OnButtonClick"/>
</VirtualizingStackPanel>
Impact
No response
Configuration
No response
Other information
No response