Blazor allows components to communicate with each other in different ways, depending on how they are related. You can pass data from a parent to a child, notify a parent of an action from the child, or even share data across unrelated components. Understanding these methods helps you build clean, maintainable applications in Blazor.

Different Ways to Pass Down Data Between Blazor Components

1. Using Parameters (Parent to Child)

The most common way to pass data.

ParentComponent.razor

@page "/parent"
<h3>Parent Component</h3><ChildComponent Message="Hello from Parent!" />

ChildComponent.razor

<h4>Child Component</h4><p>@Message</p>@code { [Parameter] public string Message { get; set; }
}

Explanation: The parent passes a value to the child via the Message parameter.

2. Using EventCallback (Child to Parent)

Passing Data from Child to Parent using EventCallback

Useful when the child component needs to notify the parent of an action.

ParentComponent.razor

<h3>Parent</h3><p>Received: @ChildData</p><ChildComponent OnDataSent="ReceiveDataFromChild" />@code { private string ChildData; private void ReceiveDataFromChild(string data) { ChildData = data; }
}

ChildComponent.razor

<button @onclick="SendData">Send Data to Parent</button>@code { [Parameter] public EventCallback<string> OnDataSent { get; set; } private async Task SendData() { await OnDataSent.InvokeAsync("Hello Parent!"); }
}

Explanation: EventCallback allows invoking a method defined in the parent from the child.

3. Using Cascading Values and Parameters

Great for passing data to deeply nested components without manually passing props.

App.razor or a Parent Component

<CascadingValue Value="AppTitle"> <NestedComponent /></CascadingValue>@code { string AppTitle = "Blazor Blog App";
}

NestedComponent.razor

<p>Cascading Value: @Title</p>@code { [CascadingParameter] public string Title { get; set; }
}

Explanation: Useful for passing themes, user info, or localization strings down the component tree.

4. Using a Shared Service (Unrelated Components or Sibling Communication via State)

Shared state or data across unrelated components.

AppState.cs (Service)

public class AppState
{ public string SharedMessage { get; set; } public event Action OnChange; public void SetMessage(string message) { SharedMessage = message; NotifyStateChanged(); } private void NotifyStateChanged() => OnChange?.Invoke();
}

Program.cs (register the service)

builder.Services.AddScoped<AppState>();

SenderComponent.razor

@inject AppState AppState
<input @bind="Message" /><button @onclick="SendMessage">Send</button>@code { private string Message; private void SendMessage() { AppState.SetMessage(Message); }
}

ReceiverComponent.razor

@inject AppState AppState
<p>Received Message: @AppState.SharedMessage</p>@code { protected override void OnInitialized() { AppState.OnChange += StateHasChanged; } public void Dispose() { AppState.OnChange -= StateHasChanged; }
}

Explanation: This is similar to a global event bus — great for managing state or broadcasting data changes.

5. Using .NET Events or Delegate Actions

You can pass delegate methods directly between components.

<!-- ParentComponent.razor --><ChildComponent ActionCallback="@DoSomething" />@code { private void DoSomething() { Console.WriteLine("Called from child!"); }
}
<!-- ChildComponent.razor --><button @onclick="ActionCallback">Call Parent Method</button>@code { [Parameter] public Action ActionCallback { get; set; }
}

Summary

MethodDirectionUse Case
[Parameter]Parent → ChildPassing data down
EventCallbackChild → ParentTriggering parent methods
CascadingParameterParent → Deep ChildApp-wide data (e.g., user, theme)
Shared ServiceAny ↔ AnyGlobal/shared state (siblings, global)
Delegate / ActionFlexiblePassing logic as parameters

Conclusion

Blazor provides a flexible and powerful component communication system. By using the right technique for the right scenario, you can ensure your Blazor apps remain modular, maintainable, and performant — whether it’s a dashboard, a blog, or a complex enterprise portal.