dotnet / maui-samples

Samples for .NET Multi-Platform App UI (.NET MAUI)
https://dot.net/maui
MIT License
3.15k stars 1.28k forks source link

Fix FlyoutPageSample OnSelectionChanged crash issue #517

Closed makazeu closed 1 month ago

makazeu commented 1 month ago

This change fixes #219, #229 and #311.

The FlyoutPageSample app runs into a crash issue on Windows with the following error message: System.InvalidOperationException: Can't change IsPresented when setting Default. Full StackTrace:

System.InvalidOperationException: Can't change IsPresented when setting Default
   at Microsoft.Maui.Controls.FlyoutPage.OnIsPresentedPropertyChanging(BindableObject sender, Object oldValue, Object newValue)
   at Microsoft.Maui.Controls.BindableObject.SetValueActual(BindableProperty property, BindablePropertyContext context, Object value, Boolean currentlyApplying, SetValueFlags attributes, SetterSpecificity specificity, Boolean silent)
   at Microsoft.Maui.Controls.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes, SetterSpecificity specificity)
   at Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value)
   at Microsoft.Maui.Controls.FlyoutPage.set_IsPresented(Boolean value)
   at FlyoutPageSample.AppFlyout.OnSelectionChanged(Object sender, SelectionChangedEventArgs e)
   at Microsoft.Maui.Controls.SelectableItemsView.SelectionPropertyChanged(SelectableItemsView selectableItemsView, SelectionChangedEventArgs args)
   at Microsoft.Maui.Controls.SelectableItemsView.SelectedItemPropertyChanged(BindableObject bindable, Object oldValue, Object newValue)
   at Microsoft.Maui.Controls.BindableObject.SetValueActual(BindableProperty property, BindablePropertyContext context, Object value, Boolean currentlyApplying, SetValueFlags attributes, SetterSpecificity specificity, Boolean silent)
   at Microsoft.Maui.Controls.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes, SetterSpecificity specificity)
   at Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value)
   at Microsoft.Maui.Controls.SelectableItemsView.set_SelectedItem(Object value)
   at Microsoft.Maui.Controls.Handlers.Items.SelectableItemsViewHandler`1.UpdateVirtualSingleSelection()
   at Microsoft.Maui.Controls.Handlers.Items.SelectableItemsViewHandler`1.UpdateVirtualSelection()
   at Microsoft.Maui.Controls.Handlers.Items.SelectableItemsViewHandler`1.PlatformSelectionChanged(Object sender, SelectionChangedEventArgs args)
   at WinRT._EventSource_global__Microsoft_UI_Xaml_Controls_SelectionChangedEventHandler.EventState.<GetEventInvoke>b__1_0(Object sender, SelectionChangedEventArgs e)
   at ABI.Microsoft.UI.Xaml.Controls.SelectionChangedEventHandler.Do_Abi_Invoke(IntPtr thisPtr, IntPtr sender, IntPtr e)

As @CodeSetting commented in #219, the problem is that IsPresented = false is incompatible with a split layout (FlyoutLayoutBehavior.Split and SplitXXX). Consider the below code in FlyoutPage.cs:

if ((!(bool)newValue) && sender is IFlyoutPageController fpc && fpc.ShouldShowSplitMode && sender is FlyoutPage fp)
{
    throw new InvalidOperationException(string.Format("Can't change IsPresented when setting {0}", fp.FlyoutLayoutBehavior));
}

Therefore, IsPresented = false should be called only with ShouldShowSplitMode being False.

makazeu commented 1 month ago

@davidbritch please help review, thanks!

davidbritch commented 1 month ago

The MacCatalyst build failure is a due to a problem with our hosted image.