CommunityToolkit / dotnet

.NET Community Toolkit is a collection of helpers and APIs that work for all .NET developers and are agnostic of any specific UI platform. The toolkit is maintained and published by Microsoft, and part of the .NET Foundation.
https://docs.microsoft.com/dotnet/communitytoolkit/?WT.mc_id=dotnet-0000-bramin
Other
3.07k stars 299 forks source link

wrong Type of Command Parameter leads to `ThrowArgumentExceptionForInvalidCommandArgument` #768

Open nor0x opened 1 year ago

nor0x commented 1 year ago

Describe the bug

I have a MAUI app on Windows which shows a list of Buttons with a Click Command Binding to the ViewModel via

<ContentPage 
             x:Name="PageSelf"
             x:DataType="local:MainViewModel"

...

          <DataTemplate x:DataType="local:MyItem">
                  <Button Text="Click Me" Command="{Binding Source={x:Reference PageSelf}, Path=BindingContext.ClickCommand}" CommandParameter="{Binding .}"/>
...        </DataTemplate>

The Command in the MainViewModel looks like the following

[RelayCommand]
private void Click(MyItem obj)
{
    //do something with obj
}

Once i click on one of the buttons the application crashes with the following exception:


Parameter "parameter" (object) cannot be of type MauiApp1.MainViewModel, as the command type requires an argument of type MauiApp1.MyItem. (Parameter 'parameter')

   at CommunityToolkit.Mvvm.Input.RelayCommand`1.ThrowArgumentExceptionForInvalidCommandArgument(Object parameter)
   at CommunityToolkit.Mvvm.Input.RelayCommand`1.Execute(Object parameter)
   at Microsoft.Maui.Controls.ButtonElement.ElementClicked(VisualElement visualElement, IButtonElement ButtonElementManager)
   at Microsoft.Maui.Controls.Button.SendClicked()
   at Microsoft.Maui.Controls.Button.Microsoft.Maui.IButton.Clicked()
   at Microsoft.Maui.Handlers.ButtonHandler.OnClick(Object sender, RoutedEventArgs e)
   at WinRT._EventSource_global__Microsoft_UI_Xaml_RoutedEventHandler.EventState.<GetEventInvoke>b__1_0(Object sender, RoutedEventArgs e)
   at ABI.Microsoft.UI.Xaml.RoutedEventHandler.Do_Abi_Invoke(IntPtr thisPtr, IntPtr sender, IntPtr e)
--- End of stack trace from previous location ---
   at WinRT.ExceptionHelpers.<ThrowExceptionForHR>g__Throw|20_0(Int32 hr)
   at ABI.Microsoft.UI.Xaml.Controls.IControlOverridesMethods.OnPointerReleased(IObjectReference _obj, PointerRoutedEventArgs e)
   at Microsoft.UI.Xaml.Controls.Control.OnPointerReleased(PointerRoutedEventArgs e)
   at Microsoft.UI.Xaml.Controls.Control.Microsoft.UI.Xaml.Controls.IControlOverrides.OnPointerReleased(PointerRoutedEventArgs e)
   at ABI.Microsoft.UI.Xaml.Controls.IControlOverrides.Do_Abi_OnPointerReleased_3(IntPtr thisPtr, IntPtr e)

Observing the error message it seems that the Type of the CommandParameter is wrongly set to MainViewModel

In the repro there is also the code in plain MAUI without the use of CommunityToolkit.Mvvm which works fine.

//works fine
public ICommand MyClickCommand { get; set; }

public MainViewModel()
{
    MyClickCommand = new Command<MyItem>(DoClick);
}

private void DoClick(MyItem item)
{
    ClickedItem = item.Name;
}

Regression

can't say for sure but I think this didn't happen in a .NET 7 project

Steps to reproduce

1. Create .NET MAUI app with a list of buttons
2. Set CommandParameter Binding to .
3. Setup [RelayCommand] in ViewModel
4. Click button
5. 💥

Expected behavior

No crash and correct passing of the Binding . object

Screenshots

No response

IDE and version

VS 2022, VS 2022 Preview

IDE version

No response

Nuget packages

Nuget package version(s)

8.2.1

Additional context

Repro: MauiApp1.zip

Original Issue: https://github.com/dotnet/maui/issues/17707

Help us help you

No, just wanted to report this

h0lg commented 3 months ago

+1 I ran into the same error using Source={x:Reference ...} when Binding a [RelayCommand] generated Command.