Компонент тостера с общим интерфейсом Blazor

#blazor #blazor-server-side

#blazor #blazor-на стороне сервера

Вопрос:

Я только набираю скорость на стороне сервера Blazor (не webassembly), поэтому простите меня, если это глупый вопрос.

То, что я пытаюсь сделать, это иметь сервис, который можно использовать для отображения тостов. Библиотека компонентов, которую я использую, взята из Syncfusion. Я могу использовать это просто отлично обычным способом, когда он встроен в каждый компонент, где это необходимо.

 <SfToast ID="toast_default" @ref="Toaster" CssClass="e-toast-success" content="@ViewModel.ToastMessage" Timeout="2000" Icon="e-meeting">
     <ToastPosition X="Right" ></ToastPosition>
</SfToast>
  

Я могу использовать это в коде, и он отображает тост, как и ожидалось.

Но у меня есть много страниц, которые используют этот код, и я бы не хотел повторяться. Я хотел бы иметь возможность использовать вышеуказанное один раз в app.razor, а затем получить ссылку на него, а затем во всем приложении. Например, в onIntializedAsync , я получаю ссылку на тостер, сохраните ее в внедренной службе. Затем я использую один и тот же сервис во всем приложении.

Я закодировал выше, но Toaster всегда имеет значение null в службе.

     public class MessageService
    {
        public SfToast Toaster { get; set; }

        public async Task SendMessage(string message)
        {
            if(this.Toaster!= null)
            {
                await this.Toaster.Show(new ToastModel() { Content = message });
            }
        }
    }
  

Это код в App.razor. Я прошел через код, и он правильно устанавливает ссылку на Toaster, но когда служба сообщений пытается заставить ее использовать ее, она равна нулю.

 @code {

    public SfToast Toaster { get; set; }

    protected override Task OnInitializedAsync()
    {
        this.MessageService.Toaster = this.Toaster;
        return base.OnInitializedAsync();
    }
}
  

Есть ли другой способ сделать это? Или я совершаю какую-то ошибку?

Комментарии:

1. Я внедряю службу с ограниченной областью действия. У этой службы есть ShowMessage метод. Мой SfToast находится только в основном макете. Основной макет задает делегат для службы с ограниченной областью действия, этот делегат может отображать сообщения через toast. Когда вы говорите службе с ограниченной областью, чтобы показать сообщение, он использует этот делегат.

2. самый простой способ — использовать CascadeParameter

3. @nAviD, спасибо, я думаю, вы правы. Если вы хотите опубликовать в качестве ответа, я приму.

4. @daniherrera, я не уверен, что вы подразумеваете под «Основным макетом, устанавливающим делегат». Можете ли вы объяснить больше?

Ответ №1:

Основываясь на ответе @nAviD, я сделал это:

MainLayout.razor настраивает параметр каскадирования. Компоненты тостера устанавливают @ref в MessageService.

 @inherits LayoutComponentBase
@using JusticeOnTheWeb.Core

<CascadingValue Value="MessageService">
    <div class="content">
        @Body
    </div>
</CascadingValue>

<SfToast ID="toast_default" @ref="MessageService.Toaster" CssClass="e-toast-success" Timeout="2000" Icon="e-meeting">
    <ToastPosition X="Right"></ToastPosition>
</SfToast>

@code{

    public MessageService MessageService { get; set; } = new MessageService();

}
  

Затем он потребляется MyComponent.razor :

 <SfButton @onclick="ShowMessage">Show Message</SfButton>


@code {

    [CascadingParameter]
    public MessageService MessageService { get; set; }

    public void ShowMessage()
    {
        this.MessageService.Show("42");
    }
}
  

Ответ №2:

Самый простой способ — использовать CascadeParameter .