Еще одной полезной возможностью Blazor является то, что компонент-предок может предоставить каскадный параметр с помощью компонента CascadingValue
, который заключает поддерево иерархии компонентов и предоставляет одно значение для всех компонентов в его поддереве.
Использование компонента CascadingValue
Одним из возможных вариантов использования компонента CascadingValue
является кастомизация темы оформления вашего приложения. Например, рассмотрим стандартный шаблон приложения Blazor Server в состав которого входит компонент счётчика, таблица с данным о метеоусловиях и компонент опроса. Для изменения стиля отрисовки каждого элемента мы могли бы задавать каждый стиль по-отдельности вручную, а можем воспользоваться каскадным параметром с использованием CascadingValue
. Чтобы продемонстрировать как работает этот компонент выполним следующие действия:
1. Создадим новый класс ThemeTemplate
со следующими свойствами:
namespace BlazorApp1 { public class ThemeTemplate { public string ButtonStyle { get; set; } public string TableStyle { get; set; } } }
Этот класс будет содержать CSS-стили кнопок и таблиц нашего приложения.
2. В макете приложения (файл MainLayout.razor
) используем CascadingValue
@inherits LayoutComponentBase <PageTitle>BlazorApp1</PageTitle> <div class="page"> <div class="sidebar"> <NavMenu /> </div> <main> <div class="top-row px-4"> <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a> </div> <CascadingValue Value="template"> <article class="content px-4"> @Body </article> </CascadingValue> </main> </div> @code { ThemeTemplate template = new ThemeTemplate() { ButtonStyle = "btn-danger", TableStyle = "table table-dark table-striped" }; }
3. Чтобы дочерние компоненты могли воспользоваться каскадным параметром, компоненты-потомки объявляют каскадные параметры с помощью атрибута [CascadingParameter]
. Каскадные значения привязаны к каскадным параметрам по типу. Объявим такие параметры на страницах Counter.razor
и FetchData.razor
Страница Counter.razor
:
@page "/counter" <PageTitle>Counter</PageTitle> <h1>Counter</h1> <p role="status">Current count: @currentCount</p> <button class="btn @Template.ButtonStyle" @onclick="IncrementCount">Click me</button> @code { [CascadingParameter] public ThemeTemplate Template { get; set; } private int currentCount = 0; private void IncrementCount() { currentCount++; } }
Страница FetchData.razor
:
@page "/fetchdata" <PageTitle>Weather forecast</PageTitle> @using BlazorApp1.Data @inject WeatherForecastService ForecastService <h1>Weather forecast</h1> <p>This component demonstrates fetching data from a service.</p> @if (forecasts == null) { <p><em>Loading...</em></p> } else { <table class="@Template.TableStyle"> <thead> <tr> <th>Date</th> <th>Temp. (C)</th> <th>Temp. (F)</th> <th>Summary</th> </tr> </thead> <tbody> @foreach (var forecast in forecasts) { <tr> <td>@forecast.Date.ToShortDateString()</td> <td>@forecast.TemperatureC</td> <td>@forecast.TemperatureF</td> <td>@forecast.Summary</td> </tr> } </tbody> </table> } @code { [CascadingParameter] public ThemeTemplate Template { get; set; } private WeatherForecast[]? forecasts; protected override async Task OnInitializedAsync() { forecasts = await ForecastService.GetForecastAsync(DateTime.Now); } }
Теперь можем запустить приложение и посмотреть как изменится стиль кнопки и таблицы:

Таблица с каскадным параметром:

Каскадное применение нескольких значений
Чтобы выполнить каскадное применение нескольких значений одного типа в одном поддереве, необходимо указать уникальную строку Name
для каждого компонента CascadingValue
и его соответствующих атрибутов [CascadingParameter]
. Например добавим ещё одну тему оформления:
Файл MainLayout.razor
@inherits LayoutComponentBase <PageTitle>BlazorApp1</PageTitle> <div class="page"> <div class="sidebar"> <NavMenu /> </div> <main> <div class="top-row px-4"> <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a> </div> <CascadingValue Value="template" Name="MainTheme"> <CascadingValue Value="otherTemplate" Name="SecondTheme"> <article class="content px-4"> @Body </article> </CascadingValue> </CascadingValue> </main> </div> @code { ThemeTemplate template = new ThemeTemplate() { ButtonStyle = "btn-danger", TableStyle = "table table-dark table-striped" }; ThemeTemplate otherTemplate = new ThemeTemplate() { ButtonStyle = "btn-success", TableStyle = "table table-dark table-striped" }; }
Файл Counter.razor
— применим вторую тему оформления
///Код компонента///// <button class="btn @Template.ButtonStyle" @onclick="IncrementCount">Click me</button> @code { @*Применяем вторую тему оформления*@ [CascadingParameter(Name ="SecondTheme")] public ThemeTemplate Template { get; set; } ///Код компонента///// }
Файл FetchData.razor
— оставим тему оформления из предыдущего примера
///Код компонента///// <table class="@Template.TableStyle"> <thead> <tr> <th>Date</th> <th>Temp. (C)</th> <th>Temp. (F)</th> <th>Summary</th> </tr> </thead> <tbody> @foreach (var forecast in forecasts) { <tr> <td>@forecast.Date.ToShortDateString()</td> <td>@forecast.TemperatureC</td> <td>@forecast.TemperatureF</td> <td>@forecast.Summary</td> </tr> } </tbody> </table> } @code { [CascadingParameter(Name ="MainTheme")] public ThemeTemplate Template { get; set; } ///Код компонента///// }
Результат применения новой темы для кнопки:
Итого
Каскадные параметры в Blazor можно задать с использованием компонента CascadingValue
. Каскадный параметр может использовать любой компонент в дереве иерархии компонента-родителя. Для использования нескольких каскадных параметров, имеющих один и тот же тип значений у компонента CascadingValue
необходимо определять уникальный параметр Name
.