AvaloniaUI / Avalonia

Develop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML. The most popular .NET UI client technology
https://avaloniaui.net
MIT License
26.1k stars 2.26k forks source link

Crash during selection change #7536

Open kant2002 opened 2 years ago

kant2002 commented 2 years ago

Admittely I have this bug in NativeAOT context, but I cannot understand why this cannot happens in regular app.

I open Structured Log Viewer on WPF binlog and start quickly double-click and change selection in the tree view.

Simplified version of what's going on. TreeView (master) + ListView (details). When something selected in the TreeView, Items in the ListView updated using

breadCrumb.Items = chain; // Crash here
breadCrumb.SelectedIndex = -1;

I suspect that if I click too quickly issue happens. Maybe I miss some standard way how I check Avalonia ListBox that right now update happens, so I postpone setting items.

Stack Trace

Unhandled Exception: System.InvalidOperationException: Cannot change source while update is in progress.
   at Avalonia.Controls.Selection.SelectionModel`1.SetSource(IEnumerable) + 0x23d
   at Avalonia.Controls.Selection.InternalSelectionModel.SetSource(IEnumerable) + 0x9c
   at Avalonia.Controls.Primitives.SelectingItemsControl.OnPropertyChanged[T](AvaloniaPropertyChangedEventArgs`1) + 0xd1
   at Avalonia.Animation.Animatable.OnPropertyChangedCore[T](AvaloniaPropertyChangedEventArgs`1) + 0x3ba
   at Avalonia.AvaloniaObject.RaisePropertyChanged[T](AvaloniaPropertyChangedEventArgs`1) + 0x99
   at Avalonia.AvaloniaObject.RaisePropertyChanged[T](AvaloniaProperty`1, Optional`1, BindingValue`1, BindingPriority) + 0xee
   at Avalonia.AvaloniaObject.SetAndRaise[T](AvaloniaProperty`1, T&, T) + 0xe9
   at StructuredLogViewer.Avalonia.Controls.BuildControl.UpdateBreadcrumb(Object) + 0xda
   at StructuredLogViewer!<BaseAddress>+0x3f1af2d
   at Avalonia.AvaloniaObject.RaisePropertyChanged[T](AvaloniaPropertyChangedEventArgs`1) + 0xd0
   at Avalonia.AvaloniaObject.RaisePropertyChanged[T](AvaloniaProperty`1, Optional`1, BindingValue`1, BindingPriority) + 0xee
   at Avalonia.AvaloniaObject.SetAndRaise[T](AvaloniaProperty`1, T&, T) + 0xe9
   at Avalonia.Controls.TreeView.set_SelectedItem(Object) + 0x41
   at StructuredLogViewer.Avalonia.Controls.BuildControl.BreadCrumb_SelectionChanged(Object, SelectionChangedEventArgs) + 0x5a
   at Avalonia.Interactivity.EventRoute.RaiseEventImpl(RoutedEventArgs) + 0x147
   at Avalonia.Interactivity.EventRoute.RaiseEvent(IInteractive, RoutedEventArgs) + 0xae
   at Avalonia.Interactivity.Interactive.RaiseEvent(RoutedEventArgs) + 0x3d
   at Avalonia.Controls.Selection.SelectionModel`1.CommitOperation(SelectionModel`1.Operation, Boolean) + 0x2f3
   at Avalonia.Controls.Selection.SelectionModelExtensions.BatchUpdateOperation.Dispose() + 0x23
   at Avalonia.Controls.Primitives.SelectingItemsControl.UpdateSelection(Int32, Boolean, Boolean, Boolean, Boolean) + 0x276
   at Avalonia.Controls.ListBox.OnPointerPressed(PointerPressedEventArgs) + 0xa4
   at Avalonia.Interactivity.RoutedEvent.<>c__DisplayClass23_0.<AddClassHandler>b__0(ValueTuple`2) + 0x5e
   at System.Reactive.AnonymousObserver`1.OnNextCore(T) + 0xc
   at System.Reactive.ObserverBase`1.OnNext(T) + 0x13
   at System.Reactive.Subjects.Subject`1.OnNext(T) + 0x69
   at Avalonia.Interactivity.EventRoute.RaiseEventImpl(RoutedEventArgs) + 0xe7
   at Avalonia.Interactivity.EventRoute.RaiseEvent(IInteractive, RoutedEventArgs) + 0xae
   at Avalonia.Interactivity.Interactive.RaiseEvent(RoutedEventArgs) + 0x3d
   at Avalonia.Input.MouseDevice.MouseDown(IMouseDevice, UInt64, IInputElement, Point, PointerPointProperties, KeyModifiers) + 0x35c
   at Avalonia.Input.MouseDevice.ProcessRawEvent(RawPointerEventArgs) + 0x163
   at Avalonia.Input.InputManager.ProcessInput(RawInputEventArgs) + 0x33
   at Avalonia.RawEventGrouper.DispatchFromQueue() + 0x75
   at Avalonia.Threading.JobRunner.RunJobs(Nullable`1) + 0x49
   at Avalonia.X11.X11PlatformThreading.HandleX11(CancellationToken) + 0x1b6
   at Avalonia.X11.X11PlatformThreading.RunLoop(CancellationToken) + 0x4f2
   at Avalonia.Threading.Dispatcher.MainLoop(CancellationToken) + 0x80
   at Avalonia.Controls.ApplicationLifetimes.ClassicDesktopStyleApplicationLifetime.Start(String[]) + 0x114
   at StructuredLogViewer!<BaseAddress>+0x420aa94

It seems to be issue with

workgroupengineering commented 2 years ago

Probaly the problem is here:

https://github.com/AvaloniaUI/Avalonia/blob/ecb0de2c32819b2ad158ba86ed1ccef8e6d6cbde/src/Avalonia.Controls/Selection/SelectionModel.cs#L301-L304

One of possible solution is call ToList() before foreach

                        var copy = _initSelectedItems.ToList();
                        foreach (T i in copy)
                        {
                            Select(ItemsView.IndexOf(i));
                        }