CommunityToolkit/Maui.Markup

[Bug] Unable to make use of BindCommand method on MenuFlyoutItem object (Desktop menu)

egvijayanand opened this issue · 12 comments

Description

Getting this exception message when the application is launched with the BindCommand method that is added to the MenuFlyoutItem object

No command + command parameter properties are registered for BindableObject type Microsoft.Maui.Controls.MenuFlyoutItem
Register command + command parameter properties for this BindableObject type

After this exception, have tried to register the command using the DefaultBindableProperties.RegisterForCommand method.

But it resulted in a different exception with the below message (as MenuFlyoutItem inherits from MenuItem):

An item with the same key has already been added. Key: Microsoft.Maui.Controls.MenuItem

Stack Trace

Link to Reproduction Sample

https://github.com/egvijayanand/dotnet-maui-samples

Solution name: MenuApp (Made available under the src folder)

The page that is causing this exception is available in the MenuPageCS.cs

Steps to Reproduce

  1. Clone the repository
  2. Navigate to the src folder
  3. Open the MenuApp solution
  4. Set the instance of MenuPageCS as the Startup page in App.xaml.cs

Expected Behavior

The command is expected to bound to the MenuFlyoutItem object and invoke the associated action.

Actual Behavior

Ends in an exception.

Basic Information

  • Version with issue: 1.0.0
  • Last known good version: NA
  • IDE: VS2022 17.3.0 Preview 3.0
  • Platform Target Frameworks:
    • iOS: NA
    • Android: NA
    • UWP: net6.0-windows10.0.19041.0 - running on Windows 11
    • MacCatalyst - Haven't tried on it due to infra constraint.
  • Android Support Library Version:
  • NuGet Packages:
  • Affected Devices:

Workaround

The event handler with the Invoke API works for now. Only Command is having the issue.

Reproduction imagery

Hey @egvijayanand!

This is the expected behavior for new MenuBarItem().BindCommand() because MenuBarItem doesn't contain a Command Property:

image

Closing as behavior expected

By the way - I love the MenuGroupExtensions you've made! Any chance you're interested in adding them to CommunityToolkit.Maui.Markup?

By the way - I love the MenuGroupExtensions you've made! Any chance you're interested in adding them to CommunityToolkit.Maui.Markup?

With pleasure. Kindly let me know the steps to take it forward.

Hey @egvijayanand!

This is the expected behavior for new MenuBarItem().BindCommand() because MenuBarItem doesn't contain a Command Property:

image

I do agree that MenuBarItem (top-level collection) doesn't have a Command attribute, but the issue is wrt to MenuFlyoutItem, the individual menu items like File, Copy, ...

Ah - apologies! I see now that we're testing MenuFlyoutItem. I'm able to reproduce + confirm the bug.

Hi @brminnick,

I see this fix is now rolled out as part of the latest v1.0.1 package release.

But I see an issue in this, change in the value of BindingContext doesn't look for the command's availability.

Generally, I would prefer to do all the necessary UI work and finally set the BindingContext to the instance of the ViewModel/any other object. That's also the case in the sample repo.

https://github.com/egvijayanand/dotnet-maui-samples/blob/f781da1336ba324bc0d87574bf0ea75b7c7f3b58/src/MenuApp/MenuPageCS.cs#L83

https://github.com/egvijayanand/dotnet-maui-samples/blob/f781da1336ba324bc0d87574bf0ea75b7c7f3b58/src/MenuApp/MenuPageCS.cs#L20

This is not working as BindingContext is null here as it is set before leaving this method.

Now make an update here set the source to the ViewModel property instance and it works fine.

But now it expects that the source (in this case, page's BindingContext) needs to be a proper instance at the time of BindCommand's invocation itself. But this is not the case in other scenarios (apart from Menus).

Any change in the value of BindingContext should reflect the values bound to it.

Kindly let me know if I'm missing anything here.

Have tried RelativeSource binding as well but the end result is the same issue.

.BindCommand(nameof(MainViewModel.QuitCommand), new RelativeBindingSource(RelativeBindingSourceMode.FindAncestorBindingContext, typeof(MainViewModel)))

I'm not sure how to fix that other than recommending to set the BindingContext first.

Any thoughts on how we could fix it?

In our sample app, we set the BindingContext in the constructor of the BasePage which avoids this problem:

protected BaseContentPage(T viewModel, string pageTitle)
{
base.BindingContext = viewModel;
Title = pageTitle;
BackgroundColor = ColorConstants.PageBackgroundColor;
}

Then how's it working for other scenarios (like Templates ...) and even I'm not sure whether this issue is in the scope of BindCommand or MAUI MenuItem itself requires to reevaluate when BindingContext changes.

Just trying the same scenario from the XAML perspective, will keep you updated on the results.

Sounds good.

Feel free to open a new Issue to address this bug.

Seems like the behavior is not consistent in XAML too, reference binding works but relative source binding fails.

Moreover, there is already an open issue (#5382) in the MAUI repo itself for Menu Commanding.

I think that is what influences here as well, let's wait for it to get addressed and revisit this, if necessary.