Course contentsShow
← C#
Lesson 1348 of 1,90812. Modern Frontend with Razor and BlazorFree lesson

Mediator Pattern for Event Handling

Decouple UI components by using an in-memory bus for application-wide notifications.

In this lesson, you will learn how to use the Mediator pattern to decouple your UI components by routing event notifications through an in-memory message bus.

The Problem: Tight Coupling

In complex Blazor applications, components often need to talk to each other without having a direct parent-child relationship. You could pass events up through multiple layers of components using EventCallback, but this leads to "prop drilling," where intermediate components become cluttered with logic they don’t actually use.

The Solution: The Mediator Pattern

Instead of components talking to each other directly, they talk to a central "Mediator." A component can publish a message to the bus, and other components can subscribe to that bus to react whenever a specific event occurs. Because you already understand the Blazor DI Container (Concept 12), we can register a singleton service to act as our bus.

Implementation Illustration

First, define a simple service to handle the communication:

public class EventBus
{
    public event Action<string>? OnNotificationReceived;
    public void Notify(string message) => OnNotificationReceived?.Invoke(message);
}

Register this in your Program.cs as a singleton: builder.Services.AddSingleton<EventBus>();.

Now, any component can inject the EventBus to communicate:

The Publisher:

@inject EventBus Bus
<button @onclick="() => Bus.Notify('Update completed!')">Trigger Event</button>

The Subscriber:

@implements IDisposable
@inject EventBus Bus

<p>@message</p>

@code {
    private string message = "Waiting...";
    protected override void OnInitialized() => Bus.OnNotificationReceived += HandleNotification;
    
    private void HandleNotification(string msg) {
        message = msg;
        InvokeAsync(StateHasChanged);
    }

    public void Dispose() => Bus.OnNotificationReceived -= HandleNotification;
}

By using this approach, the button doesn’t need to know who is listening, and the listener doesn’t need to know which component triggered the action. This keeps your components clean, modular, and focused solely on their own rendering logic.

Key Takeaway: The Mediator pattern replaces direct component dependencies with an event-driven bus, allowing disconnected parts of your UI to communicate seamlessly without knowing about each other’s existence.