BlazorでPubSub通信をやってみる

[AKSoftware.Blazor.Utilities](https://github.com/aksoftware98/blazor-utilities)　というユーティリティを使って、Blazor Applicationで、PubSub型のコンポーネント間通信を行いたいと思います。
例ではBlazorテンプレートの`Counter`コンポーネントからサイドバーの`NavMenu`コンポーネントに対し、イベントを発行してみます。

![Animation4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110304/307718bd-c05f-ac6d-421e-112dc687a650.gif)

[AKSoftware.Blazor.Utilities](https://github.com/aksoftware98/blazor-utilities)は、XamarinでのMessagingCenterの仕組みをBlazorでも使えるようにしたユーティリティです。

https://github.com/aksoftware98/blazor-utilities

https://docs.microsoft.com/ja-jp/xamarin/xamarin-forms/app-fundamentals/messaging-center

# 使用方法
### 送信(Publish)側

使用方法はXamarinでのMessagingCenterと同様です。送信時側は、インスタンスとメッセージ識別子、値を渡します。値は渡さずにメッセージ識別子だけ渡すこともできます。

```javascript:Counter.razor
@page "/counter"

@using AKSoftware.Blazor.Utilities

<PageTitle>Counter</PageTitle>

<h1>Counter</h1>

<p role="status">Current count: @currentCount</p>


<button class="btn btn-primary" @onclick="IncrementCount">Click me</button><button class="btn btn-primary" style="margin-left:5px" @onclick="ClearCount">Clear</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;

        SendMessage();
    }


    private void ClearCount()
    {
        currentCount = 0;

        SendMessage();

    }

    /// <summary>
    /// "notification"メッセージPublishする
    /// </summary>
    private void SendMessage()
    {
        MessagingCenter.Send(this, "notification", currentCount);
    }

}
```
### 受信(Subscribe)側

受信側は送信側の型によって送信されたメッセージに対し、コールバックするデリゲートを用意してあげます。

```javascript:NaviMenu.razor
@using AKSoftware.Blazor.Utilities
@implements IDisposable

@if(cnt>0)
{
    <PageTitle>Counter(@cnt)</PageTitle>
}

<div class="top-row ps-3 navbar navbar-dark">
    <div class="container-fluid">
        <a class="navbar-brand" href="">BlazorAppPubSubMessage</a>
        <button title="Navigation menu" class="navbar-toggler" @onclick="ToggleNavMenu">
            <span class="navbar-toggler-icon"></span>
        </button>
    </div>
</div>

<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
    <nav class="flex-column">
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
                <span class="oi oi-home" aria-hidden="true"></span> Home
            </NavLink>
        </div>
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="counter">
                <span class="oi oi-plus" aria-hidden="true"></span> Counter

            @if(cnt>0)
            {
                <span class="badge bg-danger">@cnt</span>
            }
            </NavLink>
        </div>
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="fetchdata">
                <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
            </NavLink>
        </div>
    </nav>
</div>

@code {
    private bool collapseNavMenu = true;

    private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;

    private void ToggleNavMenu()
    {
        collapseNavMenu = !collapseNavMenu;
    }

    private int cnt = 0;

    //
    // notificationを Subscribe
    //
    protected override void OnInitialized()
    {
        MessagingCenter.Subscribe<BlazorAppPubSubMessage.Pages.Counter,int>(this, "notification", (sendar,arg) =>
        {
            cnt = arg;
            this.StateHasChanged();
        });
    }

    public void Dispose()
    {
        MessagingCenter.Unsubscribe<BlazorAppPubSubMessage.Pages.Counter, int>(this, "notification");
    }

}

```

この仕組みを使うとコンポートの親子関係を気にせず使用できます。例えば、ショッピングサイトでカートに追加された場合に`Bagde`して通知するなど、DIコンテナに登録しなくても使えるコンポーネント間通信としてカジュアルに使うことができますね:v: