Содержание
В предыдущей части мы рассмотрели обработку событий в html-элементах. По большому счёту, обработка событий компонентов Razor практически ничем не отличается от рассмотренного ранее механизма, но в этой части мы немного глубже погрузимся в вопросы обработки событий в Razor
Обработчики событий в Razor
Посмотрим ещё раз на обработчик события Click у кнопки компонента Counter в шаблонном приложении Blazor Hybrid:
Чтобы передавать события между родительскими и дочерними компонентами, применяется специальный тип — структура EventCallback, которая представлена в двух формах:
EventCallbackEventCallback<T>
В нашем случае использована вторая форма этой структуры — EventCallback<MouseEventArgs>. Если используется такой вид структуры для передачи событий, то обработчик события может принимать аргументы события. Например, в прошлой части мы использовали объект типа MouseEventArgs, чтобы определить какой действие необходимо выполнить — добавить или вычесть единицу из значений счётчика.
По сути, html-элемент button — это дочерний компонент нашего компонента Razor (в данном случае, компонента Counter). Поэтому ничто нам не мешает применить точно такой же подход к обработки событий непосредственно между компонентами Razor. Чтобы определить в компоненте Razor какое-либо событие, мы должны создать параметр компонента с типом EventCallback или EventCallback<T>, а для обработки этого события в родительском компоненте назначить параметру обработчик.
Обработка событий компонентов Razor
Использование EventCallback
Этот тип применяется, если нашему обработчику события не требуются никакие дополнительные сведения о событии. Создадим новое приложение Blazor Hybrid и изменим код компонента Counter следующим образом:
@page "/counter"
<button class="btn btn-primary" @onclick="OnClick">Click me</button>
@code {
[Parameter]
public EventCallback OnClick { get; set; }
}
Теперь перейдем в файл Home.razor и изменим его код:
@page "/"
<h1>Hello, world!</h1>
<p>Значение счётчика: @counter</p>
<Counter OnClick="IncCounter"></Counter>
@code{
int counter = 0;
private void IncCounter()
{
counter++;
}
}
У компонента Counter мы создали событие OnClick:
[Parameter]
public EventCallback OnClick { get; set; }
Далее, мы добавили компонент Counter на страницу Home, то есть Counter у нас стал дочерним компонентов для Home и назначили компоненту обработчик события:
<Counter OnClick="IncCounter"></Counter>
@code{
int counter = 0;
private void IncCounter()
{
counter++;
}
}
Теперь можно запустить приложение и убедиться, что на главной странице при клике по кнопке значение счётчика увеличивается на 1.
Здесь мы фактически вынесли логику компонента во вне. Давайте немного перепишем компонент Counter, а заодно посмотрим на ещё один вариант использования собственных событий компонентов Razor. Перепишем код компонента следующим образом:
@page "/counter"
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
[Parameter]
public EventCallback OnFullCounter { get; set; }
private async Task IncrementCount()
{
if (currentCount == 10)
{
await OnFullCounter.InvokeAsync();
}
else
currentCount++;
}
}
Здесь мы, по сути, вернули работу Counter к первоначальному виду. Но, при этом, объявили новое событие:
[Parameter]
public EventCallback OnFullCounter { get; set; }
Обратите внимание, как вызывается обработчик этого события:
OnFullCounter.InvokeAsync();
Здесь мы вызываем метод InvokeAsync() у EventCallback. Этот метод выполняет делегат, ассоциированный с событием. В нашем случае, как только значение счётчика достигнет 10, будет вызываться обработчик события. Теперь изменим код Home.razor следующим образом:
@page "/"
<h1>Hello, world!</h1>
@if (showAlert)
{
<div class="alert alert-danger" role="alert">
Значение счётчика достигло максимального значения
</div>
}
<br />
<Counter OnFullCounter="FullCounter"></Counter>
@code{
bool showAlert = false;
private void FullCounter()
{
showAlert = true;
}
}
Всё, что делает наш обработчик события — это меняет значение у showAlert с false на true. В разметке компонента showAlert используется для определения того, необходимо ли показывать сообщение пользователю:
@if (showAlert)
{
<div class="alert alert-danger" role="alert">
Значение счётчика достигло максимального значения
</div>
}
Теперь запустим приложение и прокликаем кнопку «Click me» десять раз. На одиннадцатый клик сработает обработчик события и мы увидим вот такое сообщение:
И раз уж мы затронули тему использования метода InvokeAsync() , то теперь можно перейти к рассмотрению следующего момента обработки событий в компонентах Razor — использованию типа EventCallback<T>.
Использование EventCallback<T>
Этот тип стоит использовать в том случае, если обработчик события должен получать какие-либо аргументы события. Например, перепишем код Counter с использованием EventCallback<T> следующим образом:
@page "/counter"
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
[Parameter]
public EventCallback<string> OnFullCounter { get; set; }
private async Task IncrementCount()
{
if (currentCount == 10)
{
await OnFullCounter.InvokeAsync("Это сообщение компонента");
}
else
currentCount++;
}
}
Здесь наше событие использует уже тип EventCallback<string>, то есть обработчик события может принимать в качестве аргумента строку. При вызове обработчика события мы воспользовались второй версией метода InvokeAsync():
public System.Threading.Tasks.Task InvokeAsync (object? arg);
В качестве параметров этот метод принимает некий объект — аргумент события. И при вызове обработчика мы это аргумент передаем:
await OnFullCounter.InvokeAsync("Это сообщение компонента");
Теперь перейдем в файл Home.razor и немного изменим его код:
@page "/"
<h1>Hello, world!</h1>
@if (showAlert)
{
<div class="alert alert-danger" role="alert">
@errorMessage
</div>
}
<br />
<Counter OnFullCounter="FullCounter"></Counter>
@code{
string errorMessage = "Значение счётчика достигло максимального значения";
bool showAlert = false;
private void FullCounter(string message)
{
if (string.IsNullOrEmpty(message) == false)
errorMessage = message;
showAlert = true;
}
}
здесь в обработчике события мы проверяем содержит ли аргумент события какое-либо значение и в зависимости от этого определяем строку сообщения, которая будет показана пользователю:
if (string.IsNullOrEmpty(message) == false)
errorMessage = message;
и так как мы передаем в обработчик строку, то теперь работа компонента будет выглядеть следующим образом:
Нетрудно догадаться, что вместо строки мы можем передавать вообще любые объекты.
Итого
Для обработки событий компонентов Razor используются типы EventCallback и EventCallback<T>. Типизированный вариант EventCallback используется в том случае, если обработчик события может получать дополнительные аргументы.

