Skip to content

"Invalid Arrange rectangle" when deleting an item from a ListBox and then scrolling #20085

@TomEdwardsEnscape

Description

@TomEdwardsEnscape

Describe the bug

If you scroll a ListBox to the end, then delete its first item, then scroll back to the top, Avalonia will throw an exception which will crash the process if unhandled. The exception is thrown due to NaNs in the arrange rect calculated by VirtualizingStackPanel.

System.InvalidOperationException: 'Invalid Arrange rectangle.'
Avalonia.Base.dll!Avalonia.Layout.Layoutable.Arrange(Avalonia.Rect rect) Line 416	C#
Avalonia.Controls.dll!Avalonia.Controls.VirtualizingStackPanel.ArrangeOverride(Avalonia.Size finalSize) Line 264	C#
Avalonia.Base.dll!Avalonia.Layout.Layoutable.ArrangeCore(Avalonia.Rect finalRect) Line 714	C#
Avalonia.Base.dll!Avalonia.Layout.Layoutable.Arrange(Avalonia.Rect rect) Line 432	C#
Avalonia.Base.dll!Avalonia.Layout.Layoutable.ArrangeOverride(Avalonia.Size finalSize) Line 767	C#
Avalonia.Base.dll!Avalonia.Layout.Layoutable.ArrangeCore(Avalonia.Rect finalRect) Line 714	C#
Avalonia.Base.dll!Avalonia.Layout.Layoutable.Arrange(Avalonia.Rect rect) Line 432	C#
Avalonia.Controls.dll!Avalonia.Controls.Presenters.ContentPresenter.ArrangeOverrideImpl(Avalonia.Size finalSize, Avalonia.Vector offset) Line 680	C#
Avalonia.Controls.dll!Avalonia.Controls.Presenters.ScrollContentPresenter.ArrangeWithAnchoring(Avalonia.Size finalSize) Line 500	C#
Avalonia.Controls.dll!Avalonia.Controls.Presenters.ScrollContentPresenter.ArrangeOverride(Avalonia.Size finalSize) Line 429	C#
Avalonia.Base.dll!Avalonia.Layout.Layoutable.ArrangeCore(Avalonia.Rect finalRect) Line 714	C#
Avalonia.Base.dll!Avalonia.Layout.Layoutable.Arrange(Avalonia.Rect rect) Line 432	C#
Avalonia.Base.dll!Avalonia.Layout.LayoutManager.Arrange(Avalonia.Layout.Layoutable control) Line 340	C#
Avalonia.Base.dll!Avalonia.Layout.LayoutManager.ExecuteArrangePass() Line 273	C#
Avalonia.Base.dll!Avalonia.Layout.LayoutManager.InnerLayoutPass() Line 239	C#
Avalonia.Base.dll!Avalonia.Layout.LayoutManager.ExecuteLayoutPass() Line 152	C#
Avalonia.Controls.dll!Avalonia.Controls.VirtualizingStackPanel.ScrollIntoView(int index) Line 501	C#
Avalonia.Controls.dll!Avalonia.Controls.Presenters.ItemsPresenter.ScrollIntoView(int index) Line 130	C#
Avalonia.Controls.dll!Avalonia.Controls.ItemsControl.ScrollIntoView(int index) Line 314	C#
Sandbox.dll!Sandbox.MainWindow.RemoveFirstItem(object sender, Avalonia.Interactivity.RoutedEventArgs e) Line 22	C#

To Reproduce

Use this XAML:

<Window xmlns="https://github.com/avaloniaui" xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' x:Class="Sandbox.MainWindow">
  <Grid RowDefinitions="*,Auto">
    <ListBox Name="MyList" DisplayMemberBinding="{ReflectionBinding}"/>
    <Button Content="Scroll and Remove" Grid.Row="1" Click="RemoveFirstItem"/>
  </Grid>
</Window>

And this C#:

using System.Collections.ObjectModel;
using System.Linq;
using Avalonia.Controls;
using Avalonia.Interactivity;

namespace Sandbox
{
    public partial class MainWindow : Window
    {
        private readonly ObservableCollection<int> _numbers = new(Enumerable.Range(0, 100));
        
        public MainWindow()
        {
            InitializeComponent();
            MyList.ItemsSource = _numbers;
        }

        private void RemoveFirstItem(object sender, RoutedEventArgs e)
        {
            MyList.ScrollIntoView(99); // you can also scroll here manually
            _numbers.RemoveAt(0);
            MyList.ScrollIntoView(0);
        }
    }
}

Open the window and click the "Scroll and remove" button.

Expected behavior

No response

Avalonia version

Git master

OS

No response

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions