FlyoutPageSample Exception
System.InvalidOperationException:“Can't change IsPresented when setting Default”
System.InvalidOperationException
HResult=0x80131509
Message=Can't change IsPresented when setting Default
Source=Microsoft.Maui.Controls
StackTrace:
在 Microsoft.Maui.Controls.FlyoutPage.OnIsPresentedPropertyChanging(BindableObject sender, Object oldValue, Object newValue)
在 Microsoft.Maui.Controls.BindableObject.SetValueActual(BindableProperty property, BindablePropertyContext context, Object value, Boolean currentlyApplying, SetValueFlags attributes, Boolean silent)
在 Microsoft.Maui.Controls.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes)
在 Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value, Boolean fromStyle, Boolean checkAccess)
在 Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value)
在 Microsoft.Maui.Controls.FlyoutPage.set_IsPresented(Boolean value)
在 FlyoutPageSample.AppFlyout.OnSelectionChanged(Object sender, SelectionChangedEventArgs e) 在 D:\Code\github\maui-samples\6.0\Navigation\FlyoutPageSample\FlyoutPageSample\AppFlyout.xaml.cs 中: 第 18 行
在 Microsoft.Maui.Controls.SelectableItemsView.SelectionPropertyChanged(SelectableItemsView selectableItemsView, SelectionChangedEventArgs args)
在 Microsoft.Maui.Controls.SelectableItemsView.SelectedItemPropertyChanged(BindableObject bindable, Object oldValue, Object newValue)
在 Microsoft.Maui.Controls.BindableObject.SetValueActual(BindableProperty property, BindablePropertyContext context, Object value, Boolean currentlyApplying, SetValueFlags attributes, Boolean silent)
在 Microsoft.Maui.Controls.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes)
在 Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value, Boolean fromStyle, Boolean checkAccess)
在 Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value)
在 Microsoft.Maui.Controls.SelectableItemsView.set_SelectedItem(Object value)
在 Microsoft.Maui.Controls.Handlers.Items.SelectableItemsViewHandler`1.UpdateVirtualSingleSelection()
在 Microsoft.Maui.Controls.Handlers.Items.SelectableItemsViewHandler`1.UpdateVirtualSelection()
在 Microsoft.Maui.Controls.Handlers.Items.SelectableItemsViewHandler`1.PlatformSelectionChanged(Object sender, SelectionChangedEventArgs args)
在 WinRT._EventSource_global__Microsoft_UI_Xaml_Controls_SelectionChangedEventHandler.EventState.<GetEventInvoke>b__1_0(Object sender, SelectionChangedEventArgs e)
在 ABI.Microsoft.UI.Xaml.Controls.SelectionChangedEventHandler.Do_Abi_Invoke(IntPtr thisPtr, IntPtr sender, IntPtr e)
FlyoutLayoutBehavior="Default"
In case it helps, I thought I'd add a bit more information. I suggest changing the title to "FlyoutPageSample exception when clicking ANY menu item".
This exception reliably occurs when one clicks on any of the menu items in the flyout (e.g. "Contacts", "TodoList", "Reminders") in the FlyoutPageSample solution.
When the click occurs, the SelectionChanged event for the associated CollectionView fires, invoking AppFlyout.OnSelectionChanged. In that method, the implementation attempts to set AppFlyout.IsPresented to false.
Digging into the stack trace, and looking at the source code for FlyoutPage, I find the following method:
static void OnIsPresentedPropertyChanging(BindableObject sender, object oldValue, object newValue)
{
if (sender is Maui.IElement element && element.IsShimmed())
{
if (sender is FlyoutPage fp && fp is IFlyoutPageController fpc && !fpc.CanChangeIsPresented)
throw new InvalidOperationException(string.Format("Can't change IsPresented when setting {0}", fp.FlyoutLayoutBehavior));
}
else
{
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));
}
}
}
All of the conditions for the second throw are met. Unfortunately, since I was using this sample to learn, I don't feel comfortable speculating on whether AppFlyout or FlyoutPage contains the flaw. Both seem a little suspect to me.
Since I'm still learning, I'm unclear why it is apparently not valid for FlyoutPage.IsPresented to be false when IFlyoutPageController.ShouldShowSplitMode is true.
If the exception is valid, it seems like the FlyoutPage code could be much simpler. For example, something like this might be better:
static void OnIsPresentedPropertyChanging(BindableObject sender, object oldValue, object newValue)
{
if (sender is FlyoutPage fp && fp is IFlyoutPageController fpc)
if ((sender is Maui.IElement element && element.IsShimmed() &&
!fpc.CanChangeIsPresented) ||
((!(bool)newValue) && fpc.ShouldShowSplitMode))
throw new InvalidOperationException(string.Format("Can't change IsPresented when setting {0}", fp.FlyoutLayoutBehavior));
}
Adding further information, the exception appears to be platform specific. On the Windows platform, the exception occurs as described in my previous post. On the Android platform, the sample works correctly.
The difference seems to be in the implementation of the FlyoutLayoutBehavior.Default behavior on each platform.
On Windows, the default implementation seems to be 'FlyoutLayoutBehavior.Split', which (for previously described reasons) triggers the exception.
On Android, the default implementation seems to be 'FlyoutLayoutBehavior.Popover', which works fine.
If the exception thrown by FlyoutPage is indeed valid, the sample code can be fixed by changing AppFlyout.xaml from:
<FlyoutPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:FlyoutPageSample"
x:Class="FlyoutPageSample.AppFlyout">
To:
<FlyoutPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:FlyoutPageSample"
x:Class="FlyoutPageSample.AppFlyout"
FlyoutLayoutBehavior="Popover">
found a not crash sample: https://github.com/uwe-e/BSE.Maui.Flyout tested on Windows, Net7, FlyoutLayoutBehavior="Default"