When trying to remove a NavigationViewItem with a dynamic MenuItemsSource, while the Item is selected, I get an exception:
System.Exception: Cannot run layout in the middle of a collection change
at FluentAvalonia.UI.Controls.ItemsRepeater.MeasureOverride(Size availableSize)
at Avalonia.Layout.Layoutable.MeasureCore(Size availableSize)
at Avalonia.Layout.Layoutable.Measure(Size availableSize)
at Avalonia.Controls.Presenters.ScrollContentPresenter.MeasureOverride(Size availableSize)
at Avalonia.Layout.Layoutable.MeasureCore(Size availableSize)
at Avalonia.Layout.Layoutable.Measure(Size availableSize)
at Avalonia.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV)
at Avalonia.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV, Boolean& hasDesiredSizeUChanged)
at Avalonia.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV)
at Avalonia.Controls.Grid.MeasureOverride(Size constraint)
at Avalonia.Layout.Layoutable.MeasureCore(Size availableSize)
at Avalonia.Layout.Layoutable.Measure(Size availableSize)
at Avalonia.Layout.Layoutable.MeasureOverride(Size availableSize)
at Avalonia.Layout.Layoutable.MeasureCore(Size availableSize)
at Avalonia.Layout.Layoutable.Measure(Size availableSize)
at Avalonia.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV)
at Avalonia.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV, Boolean& hasDesiredSizeUChanged)
at Avalonia.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV)
at Avalonia.Controls.Grid.MeasureOverride(Size constraint)
at Avalonia.Layout.Layoutable.MeasureCore(Size availableSize)
at Avalonia.Layout.Layoutable.Measure(Size availableSize)
at Avalonia.Layout.LayoutManager.Measure(Layoutable control)
at Avalonia.Layout.LayoutManager.Measure(Layoutable control)
at Avalonia.Layout.LayoutManager.Measure(Layoutable control)
at Avalonia.Layout.LayoutManager.Measure(Layoutable control)
at Avalonia.Layout.LayoutManager.ExecuteMeasurePass()
at Avalonia.Layout.LayoutManager.InnerLayoutPass()
at Avalonia.Layout.LayoutManager.ExecuteLayoutPass()
at Avalonia.Layout.Layoutable.UpdateLayout()
at FluentAvalonia.UI.Controls.ViewportManager.OnBringIntoViewRequested(RequestBringIntoViewEventArgs args)
at FluentAvalonia.UI.Controls.ItemsRepeater.OnBringIntoViewRequested(Object sender, RequestBringIntoViewEventArgs args)
at Avalonia.Interactivity.Interactive.<AddHandler>g__InvokeAdapter|4_0[TEventArgs](Delegate baseHandler, Object sender, RoutedEventArgs args)
at Avalonia.Interactivity.Interactive.<>c__4`1.<AddHandler>b__4_1(Delegate baseHandler, Object sender, RoutedEventArgs args)
at Avalonia.Interactivity.EventRoute.RaiseEventImpl(RoutedEventArgs e)
at Avalonia.Interactivity.EventRoute.RaiseEvent(Interactive source, RoutedEventArgs e)
at Avalonia.Interactivity.Interactive.RaiseEvent(RoutedEventArgs e)
at Avalonia.Controls.ControlExtensions.BringIntoView(Control control, Rect rect)
at Avalonia.Controls.ControlExtensions.BringIntoView(Control control)
at Avalonia.Controls.ScrollViewer.OnGotFocus(GotFocusEventArgs e)
at Avalonia.Input.InputElement.<>c.<.cctor>b__32_0(InputElement x, GotFocusEventArgs e)
at Avalonia.Interactivity.RoutedEvent`1.<>c__DisplayClass1_0`1.<AddClassHandler>g__Adapter|0(Object sender, RoutedEventArgs e)
at Avalonia.Interactivity.RoutedEvent.<>c__DisplayClass23_0.<AddClassHandler>b__0(ValueTuple`2 args)
at Avalonia.Reactive.AnonymousObserver`1.OnNext(T value)
at Avalonia.Reactive.LightweightObservableBase`1.PublishNext(T value)
at Avalonia.Reactive.LightweightSubject`1.OnNext(T value)
at Avalonia.Interactivity.RoutedEvent.InvokeRaised(Object sender, RoutedEventArgs e)
at Avalonia.Interactivity.EventRoute.RaiseEventImpl(RoutedEventArgs e)
at Avalonia.Interactivity.EventRoute.RaiseEvent(Interactive source, RoutedEventArgs e)
at Avalonia.Interactivity.Interactive.RaiseEvent(RoutedEventArgs e)
at Avalonia.Input.KeyboardDevice.SetFocusedElement(IInputElement element, NavigationMethod method, KeyModifiers keyModifiers)
at Avalonia.Input.FocusManager.Focus(IInputElement control, NavigationMethod method, KeyModifiers keyModifiers)
at Avalonia.Input.InputElement.Focus(NavigationMethod method, KeyModifiers keyModifiers)
at FluentAvalonia.UI.Controls.ViewManager.MoveFocusFromClearedIndex(Int32 clearedIndex)
at FluentAvalonia.UI.Controls.ViewManager.ClearElementToElementFactory(Control element)
at FluentAvalonia.UI.Controls.ViewManager.ClearElement(Control element, Boolean isClearedDueToCollectionChange)
at FluentAvalonia.UI.Controls.ItemsRepeater.ClearElementImpl(Control element)
at FluentAvalonia.UI.Controls.RepeaterLayoutContext.RecycleElementCore(Control element)
at FluentAvalonia.UI.Controls.VirtualizingLayoutContext.RecycleElement(Control element)
at FluentAvalonia.UI.Controls.ElementManager.ClearRealizedRange(Int32 realizedIndex, Int32 count)
at FluentAvalonia.UI.Controls.ElementManager.ClearRealizedRange()
at FluentAvalonia.UI.Controls.ElementManager.DataSourceChanged(Object source, NotifyCollectionChangedEventArgs args)
at FluentAvalonia.UI.Controls.FlowLayoutAlgorithm.OnItemsSourceChanged(Object source, NotifyCollectionChangedEventArgs args, VirtualizingLayoutContext context)
at FluentAvalonia.UI.Controls.StackLayout.OnItemsChangedCore(VirtualizingLayoutContext context, Object source, NotifyCollectionChangedEventArgs args)
at FluentAvalonia.UI.Controls.ItemsRepeater.OnItemsSourceViewChanged(Object sender, NotifyCollectionChangedEventArgs args)
at FluentAvalonia.UI.Controls.FAItemsSourceView.OnItemsSourceChanged(NotifyCollectionChangedEventArgs args)
at FluentAvalonia.UI.Controls.FAItemsSourceView.OnCollectionChanged(NotifyCollectionChangedEventArgs args)
at FluentAvalonia.Core.SimpleObserver`1.OnNext(T value)
at Avalonia.Reactive.LightweightObservableBase`1.PublishNext(T value)
at Avalonia.Collections.NotifyCollectionChangedExtensions.WeakCollectionChangedObservable.OnEvent(Object sender, WeakEvent ev, NotifyCollectionChangedEventArgs e)
at Avalonia.Utilities.WeakEvent`2.Subscription.OnEvent(Object sender, TEventArgs eventArgs)
at Avalonia.Utilities.WeakEvents.<>c__DisplayClass5_0.<.cctor>b__5(Object _, NotifyCollectionChangedEventArgs e)
at System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
at AvaloniaTests.ViewModels.MainWindowViewModel.Test() in ...\AvaloniaTests\AvaloniaTests\ViewModels\MainWindowViewModel.cs:line 16
at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_0(Object state)
at Avalonia.Threading.SendOrPostCallbackDispatcherOperation.InvokeCore()
at Avalonia.Threading.DispatcherOperation.Execute()
at Avalonia.Threading.Dispatcher.ExecuteJob(DispatcherOperation job)
at Avalonia.Threading.Dispatcher.ExecuteJobsCore(Boolean fromExplicitBackgroundProcessingCallback)
at Avalonia.Threading.Dispatcher.Signaled()
at Avalonia.Win32.Win32DispatcherImpl.DispatchWorkItem()
at Avalonia.Win32.Win32Platform.WndProc(IntPtr hWnd, UInt32 msg, IntPtr wParam, IntPtr lParam)
at Avalonia.Win32.Interop.UnmanagedMethods.DispatchMessage(MSG& lpmsg)
at Avalonia.Win32.Win32DispatcherImpl.RunLoop(CancellationToken cancellationToken)
at Avalonia.Threading.DispatcherFrame.Run(IControlledDispatcherImpl impl)
at Avalonia.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
at Avalonia.Threading.Dispatcher.MainLoop(CancellationToken cancellationToken)
at Avalonia.Controls.ApplicationLifetimes.ClassicDesktopStyleApplicationLifetime.Start(String[] args)
at Avalonia.ClassicDesktopStyleApplicationLifetimeExtensions.StartWithClassicDesktopLifetime(AppBuilder builder, String[] args, Action`1 lifetimeBuilder)
at AvaloniaTests.Program.Main(String[] args) in ...\AvaloniaTests\AvaloniaTests\Program.cs:line 13
Desktop/Platform (please complete the following information):
OS: Windows 11
FluentAvalonia Version 2.1.0-preview5
Avalonia Version 11.1.0-beta2
Additional context
The code throws somewhere deep down when trying to remove the focus from the element, I think. Therefore I could create a workaround where I manually selected a different menu item before removing the old one, but it would be great if that would not be necessary.
Note to the minimal repo:
I added basically the same code with the list box to show that the problem does not exist here.
I added a short delay between clicking and removing to give the UI some time to render the style which shows the selected item
Describe the bug
When trying to remove a NavigationViewItem with a dynamic MenuItemsSource, while the Item is selected, I get an exception:
Screenshots
Desktop/Platform (please complete the following information):
Additional context The code throws somewhere deep down when trying to remove the focus from the element, I think. Therefore I could create a workaround where I manually selected a different menu item before removing the old one, but it would be great if that would not be necessary.
Note to the minimal repo: