14

In my view models, I wanted to use the source generators in CommunityToolkit.Mvvm but for some reason I can't seem to use [ICommand] attribute with my action methods.

The error I get is:

Cannot apply attribute class 'ICommand' because it is abstract

Here's the base class for my view model model.

using CommunityToolkit.Mvvm.ComponentModel;

namespace MyApp.ViewModels
{
    public partial class BaseViewModel : ObservableObject
    {
        [ObservableProperty]
        bool isBusy = false;

        [ObservableProperty]
        string title = string.Empty;
    }
}

And here's my view model class:

public class MyViewModel : BaseViewModel
{
   [ObservableProperty]
   string firstName;

   [ObservableProperty]
   string lastName;

   [ICommand] // <-- This is where I get the error I mentioned above
   async Task DoSomething()
   {
       // Do something here...
   }
}
Sam
  • 26,817
  • 58
  • 206
  • 383
  • Hey Sam, I'll try to reproduce this when I have some free time. – Michal Diviš Jun 10 '22 at 20:26
  • 1
    Perhaps you're accidentally using the ICommand interface from System.Windows.Input, instead of the ICommandAttribute from the CommunityTookit. Try to replace `[ICommand]` with `[CommunityToolkit.Mvvm.Input.ICommand]` and see if that was the case. – Luca Clavarino Jun 12 '22 at 10:34
  • 1
    I was sure you were right because I am using `System.Windows.Input` but I don't find `ICommand` in `CommunityToolkit.Mvvm.Input.ICommand`. I'm using version `8.0.0-preview4`. The only thing I see in there is `RelayCommand` but that I can't seem to use it as an attribute and it doesn't work in the above example. – Sam Jun 13 '22 at 04:19

3 Answers3

22

The problem seems to be what @Luca Clavarino mentioned in the comments:

Perhaps you're accidentally using the ICommand interface from System.Windows.Input,instead of the ICommandAttribute from the CommunityTookit. Try to replace [ICommand] with [CommunityToolkit.Mvvm.Input.ICommand] and see if that was the case.

And I think I know why this might be happening to you. The ICommandAttribute seems to be missing in CommunityToolkit.Mvvm 8.0.0-preview4 so intellisense won't offer the using CommunityToolkit.Mvvm.Input statement and instead offers using System.Windows.Input;.

The problem can be resolved by downgrading to CommunityToolkit.Mvvm 8.0.0-preview3, that version works fine for me.

Here's a working sample (using CommunityToolkit.Mvvm 8.0.0-preview3).

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

namespace MyApp.ViewModels
{
    public partial class BaseViewModel : ObservableObject
    {
        [ObservableProperty]
        bool isBusy = false;

        [ObservableProperty]
        string title = string.Empty;
    }

    public partial class MyViewModel : BaseViewModel
    {
        [ObservableProperty]
        string firstName;

        [ObservableProperty]
        string lastName;

        [ICommand] //works in 8.0.0-preview3
        async Task DoSomething()
        {
            // Do something here...
        }
    }
}

I've also noticed that while the ICommandAttribute is gone in 8.0.0-preview4, there's a RelayCommandAttribute instead. Maybe they've simply renamed it.

Using the RelayCommandAttribute instead of ICommandAttribute in 8.0.0-preview4 seems to be working.

[RelayCommand] //works in 8.0.0-preview4
async Task DoSomething()
{
    // Do something here...
}

EDIT

Yes, they've renamed the ICommandAttribute to RelayCommandAttribute. It's metioned in the breaking changes section of the 8.0.0-preview4 release notes.

Michal Diviš
  • 2,008
  • 12
  • 19
  • 3
    Thank you! As you said, `[ICommand]` is now `[RelayCommand]` and another important point is that if we name the method `DoSomething()`, the generated command will be `DoSomethingCommand()`. This is the reason why I couldn't get `[RelayCommand]` to work before. Once I referenced the method with `Command` suffix, it worked fine. Thanks again for your help! – Sam Jun 14 '22 at 22:50
  • Excellent, this is the only helpful thread that answers a search of "relaycommand is not an attribute class". – scotty Aug 24 '22 at 05:54
15

The accepted answer has a lot of text just to say in 8.0.0 Preview 4 the [ICommand] attribute was renamed to [RelayCommand]. It is listed in the breaking changes of the release notes.

IKavanagh
  • 6,089
  • 11
  • 42
  • 47
0

Works with 8.0.0-preview3 not 8.0.0-preview4 or latest release 8.0.0.

Shades49
  • 15
  • 4
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 10 '22 at 11:34