How to get reference to the Blazor MainLayout from a child component

I put some global Blazor Components in the MainLayout of my Blazor Server side app. They are used to show Alert, Confirmation, Warning, ...

From a child component, how can I get the reference to the MainLayout in order to call my global Alert, Confirmation functions?

The child component is dynamic and may be in any nested level. So we don't know how many level from it to the root MainLayout.

It is like the concept of ApplicationContext.MainForm in Winform app.


You can cascade a reference to the MainLayout component to its children and thier descendants by using the CascadingValue component as demonstrated below:

@inherits LayoutComponentBase

<CascadingValue Value="this">
<div class="sidebar">
    <NavMenu />
</div>

<div class="main">
    <div class="top-row px-4">
        <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
    </div>

    <div class="content px-4">
        @Body
    </div>
</div>

</CascadingValue>

And in the child components you should define a CascadingParameter property that receive the reference as the following:

 [CascadingParameter]
 public MainLayout Layout { get; set; }

Now you can do something interesting from the child component.


What about using a registered service(singleton or scoped). This service implements an event that is thrown when a child component wants to display the alert. The MainLayout listens to the event of the alert service and if a new event is thrown then the MainLayout shows the alert.

The service could look like following:

 public class AlertService
{
    public event EventHandler<AlertEventArgs> AlertMessageChanged;

    protected virtual void OnAlertMessageChanged(AlertEventArgs e)
    {
        EventHandler<AlertEventArgs> handler = AlertMessageChanged;
        if (handler != null)
        {
            handler(this, e);
        }
    }

    public void SetAlertMessage(string alertMessage)
    {
        var eventArgs = new AlertEventArgs();
        eventArgs.AlertMessage = alertMessage;
       OnAlertMessageChanged(eventArgs);
    }
}

In the AlertEventArgs there could be a property "AlertMessage" or something like that. And in the MainLayout you register an event handler for the OnAlertMessageChanged event

@inherits LayoutComponentBase
@inject AlertService alertService   

<div class="main">
   ...
</div>

@code { 

    override void OnInitialized()
    {
        base.OnInitialized();
        alertService.AlertMessageChanged += HandleAlertMessageChanged;
    }

    private void HandleAlertMessageChanged(AlertEventArgs args)
    {
        //Show the alert
    }
}

For confirmations or warnings, you can extend the existing service or you create new ones and of course, you need to register the services.