user12228709
user12228709

Reputation:

Set EventCallback<string> outside of a Blazor component?

I am building a Blazor ProgressBar demo, and I am attempting to move some code out of my Blazor component into a C# class called ProgressManager. This is so I can abstract the code and make the ProgressManager a CascadingParameter to the ProgressBar component.

I know how to set an EventCallback parameter for a component like this:

[Parameter]
public EventCallback<string> UpdateNotification { get; set; }

What I don't know how to do is set this same type of property on a C# class.

I have this code in my Start method:

public void ShowProgressSimulation()
{
    // Create a ProgressManager
    this.ProgressManager = new ProgressManager();
    this.ProgressManager.UpdateNotification = Refresh;
    this.ProgressManager.Start();
    
    // Refresh the UI
    StateHasChanged();
}

The part that does not work is: this.ProgressManager.UpdateNotification = Refresh;

The error is:

Cannot convert method group 'Refresh' to non-delegate type 'EventCallback'. Did you intend to invoke the method?

I also tried: this.ProgressManager.UpdateNotification += Refresh;

And this leads to "EventCallback cannot be applied to method group" (paraphrasing).

Upvotes: 32

Views: 12492

Answers (3)

Ekus
Ekus

Reputation: 1880

I needed to toggle the handler on and off and check the .HasDelegate status, and also pass a parameter (of type Item) to the delegate, this is what worked for me:

private void toggleHandler()
{
    if (isRowClickHandler)
    { // remove handler
        myGrid.OnRowClick = new EventCallback<Item>(null, null); 
        // EventCallback<Item>.Empty didn't work, OnRowClick.HasDelegate still returned true
    }
    else
    { // add handler
        myGrid.OnRowClick = new EventCallback<Item>(myGrid, (Action<Item>)handleRowClick);
    }
    isRowClickHandler = !isRowClickHandler;
}

private void handleRowClick(Item item)
{
    App.ShowNotification(Status.Success, $"Click invoked on row with value {item.Value1}");
}

Upvotes: 0

Niek Jannink
Niek Jannink

Reputation: 1186

You can also use the following code to create an EventCallBack though the factory without having to new up the EventCallbackFactory

Button.Clicked = EventCallback.Factory.Create( this, ClickHandler );

Upvotes: 20

Sipke Schoorstra
Sipke Schoorstra

Reputation: 3409

Turns out you can assign an event callback from C# code like this:

this.ProgressManager.UpdateNotification = new EventCallback(this, (Action)Refresh);

void Refresh() {}

It also works with async methods, e.g.:

this.ProgressManager.UpdateNotification = new EventCallback(this, (Func<ValueTask>)RefreshAsync);

ValueTask RefreshAsync() {}

UPDATE

You can also use EventCallbackFactory to more conveniently create event callback objects, e.g.:

new EventCallbackFactory().Create(this, Refresh)

Upvotes: 32

Related Questions