scottdavidwalker
scottdavidwalker

Reputation: 1541

Blazor - cannot convert from 'method group' to 'EventCallback'

I have a parent component and a child component with an event callback where I want it to pass back a type of T.

The issue I'm having is that I have an error about converting

MethodGroup to EventCallback.

If I convert this to using an Action then it works, but I can't do it async which isn't ideal.

Any ideas what I'm doing wrong?


Parent

<Child DeleteCallback="@OnDelete"></Child>

public async Task OnDelete(T item)
{ ... }

Child

@typeparam T

[Parameter]
public EventCallback<T> DeleteCallback { get; set; }

 <a @onclick="() => DeleteCallback.InvokeAsync(item)"></a>

I've added a repo here explaining the problem. Looking at the Issues for Blazor, this should;ve been fixed in 2019. https://github.com/scott-david-walker/EventCallbackError

Upvotes: 58

Views: 70786

Answers (12)

sourcecode
sourcecode

Reputation: 4601

The following Solution is working for me.

<InputSelect ValueChanged="@((string s) => DoThing(s))" ValueExpression="@(()=> form.MyProperty)"> <option value="0">0</option> <option value="100">100</option> <option value="200">200</option> <option value="300">300</option> </InputSelect>

`@code { MyForm form = new MyForm();

void DoThing(string s)
{
    form.MyProperty = s;
}

public class MyForm
{
    public string MyProperty { get; set; }
}

}'

Upvotes: 1

alelom
alelom

Reputation: 3008

After trying all other solutions proposed here, including:

  • Making sure I was providing T=myType
  • Clean and rebuild
  • Restart Visual Studio
  • Rename the method by appending a letter to its name and aligning its binding

The only thing that worked for me was literally deleting the line with the binding, saving, recompiling, then writing it back.

In doing so, I in fact realized that I was typing:

SelectedItemChanged="@SelectedItemsChanged"

instead of:

SelectedItemsChanged="@SelectedItemsChanged"

I was missing an s in the binding. The method itself had a signature receiving a HashSet of my type, so it could only deal with Items, not a single item.

Upvotes: 6

Ogglas
Ogglas

Reputation: 70116

In my case I got the error

Error (active) CS1503 Argument 2: cannot convert from 'method group' to 'EventCallback'

for ValueChanged with the following code:

<MatAutocompleteList TItem="UseCase" Items="@selectUseCases" ValueChanged=@SelectUseCases>
                        <ItemTemplate>
                            @context?.Label
                        </ItemTemplate>
                    </MatAutocompleteList>

@code
{
    private UseCase SelectUseCases(UseCase useCaseDto)
    {
        if (useCaseDto != null)
        {
            //Do stuff
            
        }
        return null;
    }
}

Changed to private void SelectUseCases(UseCase useCaseDto), removed all returns and the error disappeared.

Upvotes: 0

Alex
Alex

Reputation: 5247

In my case it was a phantom error among tens others that never went away no matter what I do. Meaning I could still build and run a solution without problems, despite so many erorrs.

What helped me was this solution: https://stackoverflow.com/a/66219566/1215913

However, I finally found a solution after a few hours of digging. To get rid of the phantom errors I closed Visual Studio, deleted the files in the following folder, and then re-opened the solution: C:\Users<Username>\AppData\Local\Temp\VSFeedbackIntelliCodeLogs\Suggestions\

The only difference is I removed all of the folders that start with VS (C:\Users\<Username>\AppData\Local\Temp\VS*) since there was no this exact path as @rovert mentions in his post.

This seems to be some common problem with Blazor and IntelliSense. I also often see that auto-formatter fails to correctly format the razor code (text indentations are a mess).

Upvotes: 0

Mthokozisi Nyoni
Mthokozisi Nyoni

Reputation: 1

Okay I just spent hours trying to figure this out. Turns out on my end the problem was I have sync fusion in the project and I had explicitly define the name space of the Event call back arguments which in my case were Microsoft.AspNetCore.Components.ChangeEventArgs in the child component and then creating an async method to pass back data to the parent.

Upvotes: 0

EricS
EricS

Reputation: 45

For anyone fighting this with the MudBlazor MudTable I found this worked use @bind-SelectedItem and don't pass any parameters to the commit function.

<MudTable T="POCO" Items="@MyState.POCOs" 
                              @bind-SelectedItem="_selectedPOCO"  
                              OnCommitEditClick="@(() => commitPOCO())"
                              CommitEditTooltip="Save Changes?">
@code {
    private POCO _selectedPOCO;

    private async void commitPOCO()
    {
        // all the changed values are in _selectedPOCO
        ...
    }

Upvotes: 3

nAviD
nAviD

Reputation: 3281

In my case, the problem solved when I defined the @typeparam manually(not by inference)(TItem="int").

<MyComponent TItem="int" OnChange="Component_Changed" />

Upvotes: 9

For some reason Visual Studio kept a previous signature I had used. Cleaning, restarting, emptying bin/obj folders etc did not work. I had to rename the method, which worked for me.

Upvotes: 7

JTvermose
JTvermose

Reputation: 342

I've experienced that the syntax was spot on and still getting this error.

Restarting Visual Studio 2019 solved the problem for me. Cleaning and rebuilding was not enough.

Upvotes: 8

Sebazzz
Sebazzz

Reputation: 1373

In my case I declared a nullable EventCallback? - you can't do that.

Upvotes: 26

Brian Parker
Brian Parker

Reputation: 14573

You were close:

<ChildComponent Item="someModel" T="SomeModel" DeleteCallback="OnDeleteSomeModel" />

@code {
    SomeModel someModel = new SomeModel();

    void OnDeleteSomeModel(SomeModel someModel)
    {
        ...
    }
}

The EventCallback uses a generic type and blazor cannot infer it if you don't pass the type to the component.

This means that if you have a EventCallback<T> you need to pass the value of T to the component e.g. T="SomeType".

Upvotes: 86

cskwg
cskwg

Reputation: 849

The following syntax worked for me:

// in the component (C#):
[Parameter]
public EventCallback<MovingEventArgs> OnMoving { get; set; }

// on the using side (Razor):
OnMoving="(Component.MovingEventArgs o) => OnMoving(o)"

// on the using side (C#):
protected void OnMoving( Component.MovingEventArgs e ) {
}

There seems to have been a change and the documentation is not up to date. This event is also using custom event arguments.

Upvotes: 7

Related Questions