Prerequisite: The interactive examples in this section require the component to use an interactive render mode such as InteractiveServer or InteractiveWebAssembly. Without an interactive render mode, event callbacks from child components are not processed. See Render modes for details.
The EventCallback<T> class is a special Blazor class that can be exposed as a Parameter
so that components can easily notify consumers when something of interest has occurred.
Once a public property of type EventCallback<T> has been declared and decorated with the [Parameter] attribute,
consuming components can specify in Razor mark-up which method to call when the event is triggered.
Adding an event to the Counter component
In a new Blazor app, edit the Components/Pages/Counter.razor file and add a new callback parameter.
[Parameter]
public EventCallback<int> OnMultipleOfThree { get; set; }
This declares a new EventCallback named OnMultipleOfThree that any consuming component can register an interest in.
The <int> specifies that the value emitted by the event callback will be a System.Int32.
Now if we edit the IncrementCount method we can emit this event whenever the counter is incremented to a multiple of 3.
private async Task IncrementCount()
{
currentCount++;
if (currentCount % 3 == 0)
await OnMultipleOfThree.InvokeAsync(currentCount);
}
Subscribing to EventCallback
Edit the Components/Pages/Home.razor page so that we embed the Counter component and subscribe to its OnMultipleOfThree event. Change its mark-up to the following.
@page "/"
Last multiple of three = @LastMultipleOfThree
<Counter OnMultipleOfThree=@UpdateLastMultipleOfThreeValue/>
@code
{
int LastMultipleOfThree = 0;
private void UpdateLastMultipleOfThreeValue(int value)
{
LastMultipleOfThree = value;
}
}
- Line 9
Declares a class member of typeintthat stores the last multiple of 3 value. - Line 3
Displays the value of LastMultipleOfThree - Line 5
Embeds the Counter component and sets its OnMultipleOfThree event to execute the UpdateLastMultipleOfThreeValue method when the event is emitted. - Line 11
The value received from the event is used to update the value of LastMultipleOfThree.

Differences between EventCallback and .NET events
Single-cast vs. Multi-cast
The most notable difference is that EventCallback<T> is a single-cast event handler, whereas .NET events are multi-cast.
Blazor EventCallback<T> is meant to be assigned a single value and can only call back a single method.
// Setting a Blazor EventCallback
<MyComponent SomeEvent=@MyMethodToCall/>
// Setting a .NET event
MyComponent.SomeEvent += MyMethodToCall;
// Unscrubscribing from the event
MyComponent.SomeEvent -= MyMethodToCall;
Class vs. Struct
.NET events (delegates) are classes, whereas Blazor EventCallback<T> is a readonly struct.
Unlike .NET delegates, EventCallback<T> cannot be null and
therefore there is no need to do any null checking when emitting the event.
// Invoking a .NET event
MyNetEvent?.Invoke(this, someValue);
// Invoking a CallbackEvent<T>
MyEventCallback.InvokeAsync(someValue);
Awaitable callbacks
Standard .NET events are synchronous, whereas Blazor EventCallback<T> is asynchronous.
As we can see in the previous example code, EventCallback<T>.InvokeAsync returns a Task that can be awaited.
Razor mark-up compatibility
It is not possible to decorate a standard .NET event with [Parameter] and
have it settable via Razor mark-up, whereas with EventCallback<T> it is.
This gives us the ability to express event callbacks in the view mark-up itself,
which makes the developer's intentions easier to see.
Automatic state change detection
Whenever a method is called from an EventCallback<T>, after the method has executed Blazor will execute StateHasChanged()
on the consuming component so it can be re-rendered in case the method called altered state.
This is not something that will happen if the consumer's method was called back via a standard .NET event, Action<T>,
or any other approach not initiated by EventCallback<T>.
For example, if we add a new [Parameter] to the Counter component of type Action<int>? and
call it whenever the current count is a multiple of two, we can see how the consuming component's render behavior is affected.
Change the Counter component to match the following code:
@page "/counter"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick=IncrementCount>Click me</button>
@code {
private int currentCount = 0;
[Parameter]
public Action<int>? OnMultipleOfTwoAction { get; set; }
[Parameter]
public EventCallback<int> OnMultipleOfThree { get; set; }
private async Task IncrementCount()
{
currentCount++;
if (currentCount % 2 == 0)
OnMultipleOfTwoAction?.Invoke(currentCount);
if (currentCount % 3 == 0)
await OnMultipleOfThree.InvokeAsync(currentCount);
}
}
- Line 13
A[Parameter]is added of typeAction<int>? - Lines 21-22
If the current count is a multiple of two, then invoke OnMultipleOfTwoAction
Now alter the Index component so that it sets a method to callback whenever the value is a multiple of two, and so it also stores and displays the last number received from OnMultipleOfTwoAction on the consumed component.
@page "/"
<ul>
<li>Last multiple of two = @LastMultipleOfTwo</li>
<li>Last multiple of three = @LastMultipleOfThree</li>
</ul>
<Counter OnMultipleOfThree=@UpdateLastMultipleOfThreeValue OnMultipleOfTwoAction=@UpdateLastMultipleOfTwoValue />
@code
{
int LastMultipleOfTwo = 0;
int LastMultipleOfThree = 0;
private Task UpdateLastMultipleOfThreeValue(int value)
{
LastMultipleOfThree = value;
return Task.CompletedTask;
}
private void UpdateLastMultipleOfTwoValue(int value)
{
LastMultipleOfTwo = value;
}
}
- Line 13
Defines a new member to store the most recent "multiple of two" value passed from the consumed component - Line 4
Displays the value of LastMultipleOfTwo in the user interface - Line 9
Sets OnMultipleOfTwo on the consumed component so that our component is notified whenever the current value is a multiple of two - Line 24
Records the last multiple of two that the consumed component has notified us of
When we run the application now and click the button a number of times,
we'll see that when UpdateLastMultipleOfTwoValue is called back via Action<int> there is no update to the view,
but when UpdateLastMultipleOfThreeValue is called back via EventCallback<int> on the next click the view is updated
and the latest value of both are displayed.

Sequence of events
| Click count | Callback executed | Consumer re-rendered |
| 1 | None | N/A |
| 2 | Action<int> |
No |
| 3 |
Action<int>EventCallback<int>
|
Yes |
| 4 | Action<int> |
No |
| 5 | None | N/A |
| 6 |
Action<int>EventCallback<int>
|
Yes |
Callee method signatures
EventCallback<T> typically calls back a method with the signature private Task SomeName(T value) -
where the exposure level of the method is unimportant.
However, Blazor will allow us to set an EventCallback<T> to call back methods with a couple of variations.
If our method does not perform any asynchronous operations, then the following implementation may start to become tedious:
public Task SomethingHappenedInChildComponent(string value)
{
// Do something with value
return Task.CompletedTask;
}
Because of this, Blazor will allow us to set EventCallback<T> to call back a method with a void return type.
public void SomethingHappenedInChildComponent(string value)
{
// Do something with value
}
Sometimes we only want to know when an event occurs, and aren't interested in the value that was passed with it. Blazor will also call back a method that excludes the value parameter.
// Either
public void SomethingHappenedInChildComponent()
{
// Do something that doesn't need the value
}
// Or
public Task SomethingHappenedInChildComponent()
{
// Do some asynchronous work that doesn't need the value
return SomeTask;
}
Non-generic EventCallback
When we only need to notify a parent that something happened without passing a value, we can use the non-generic EventCallback instead of EventCallback<T>. It works the same way but omits the typed payload.
[Parameter]
public EventCallback OnSomethingHappened { get; set; }
Invoking it is the same, but without a value argument:
await OnSomethingHappened.InvokeAsync();
A parent component can subscribe to it like any other event callback:
<ChildComponent OnSomethingHappened=@HandleSomethingHappened/>
private void HandleSomethingHappened()
{
// No value parameter needed
}
