Поделиться через


Передача параметров корневого компонента в ASP.NET Core Blazor Hybrid

Примечание.

Это не последняя версия этой статьи. В текущем выпуске см . версию .NET 9 этой статьи.

Предупреждение

Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в политике поддержки .NET и .NET Core. В текущем выпуске см . версию .NET 9 этой статьи.

Внимание

Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

В текущем выпуске см . версию .NET 9 этой статьи.

В этой статье объясняется, как передать параметры корневого Blazor Hybrid компонента в приложении.

Класс RootComponent BlazorWebView определяет Parameters свойство типа IDictionary<string, object?>?, представляющее необязательный словарь параметров для передачи корневому компоненту:

В следующем примере модель представления передается корневому компоненту, который далее передает модель представления в виде каскадного типа Razor компоненту в Blazor части приложения. Пример основан на примере клавиатуры .NET MAUI в документации:

Хотя в примере клавиатуры основное внимание уделяется реализации шаблона MVVM в .NET MAUIBlazor Hybrid приложениях:

  • Словарь объектов, переданных корневым компонентам, может включать любой тип для любой цели, в которой необходимо передать один или несколько параметров корневому компоненту для использования Razor компонентами в приложении.
  • Основные понятия, показанные в следующем .NET MAUIBlazor примере, одинаковы для приложений Windows Forms Blazor и приложений WPF Blazor .

Поместите в приложение следующую модель .NET MAUIBlazor Hybrid представления.

KeypadViewModel.cs:

using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;

namespace MauiBlazor;

public class KeypadViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private string _inputString = "";
    private string _displayText = "";
    private char[] _specialChars = { '*', '#' };

    public ICommand AddCharCommand { get; private set; }
    public ICommand DeleteCharCommand { get; private set; }

    public string InputString
    {
        get => _inputString;
        private set
        {
            if (_inputString != value)
            {
                _inputString = value;
                OnPropertyChanged();
                DisplayText = FormatText(_inputString);

                // Perhaps the delete button must be enabled/disabled.
                ((Command)DeleteCharCommand).ChangeCanExecute();
            }
        }
    }

    public string DisplayText
    {
        get => _displayText;
        set
        {
            if (_displayText != value)
            {
                _displayText = value;
                OnPropertyChanged();
            }
        }
    }

    public KeypadViewModel()
    {
        // Command to add the key to the input string
        AddCharCommand = new Command<string>((key) => InputString += key);

        // Command to delete a character from the input string when allowed
        DeleteCharCommand =
            new Command(
                // Command strips a character from the input string
                () => InputString = InputString.Substring(0, InputString.Length - 1),

                // CanExecute is processed here to return true when there's something to delete
                () => InputString.Length > 0
            );
    }

    string FormatText(string str)
    {
        bool hasNonNumbers = str.IndexOfAny(_specialChars) != -1;
        string formatted = str;

        // Format the string based on the type of data and the length
        if (hasNonNumbers || str.Length < 4 || str.Length > 10)
        {
            // Special characters exist, or the string is too small or large for special formatting
            // Do nothing
        }

        else if (str.Length < 8)
            formatted = string.Format("{0}-{1}", str.Substring(0, 3), str.Substring(3));

        else
            formatted = string.Format("({0}) {1}-{2}", str.Substring(0, 3), str.Substring(3, 3), str.Substring(6));

        return formatted;
    }

    public void OnPropertyChanged([CallerMemberName] string name = "") =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}

В примере этой статьи корневое пространство имен приложения — MauiBlazorэто . Измените пространство KeypadViewModel имен, соответствующее корневому пространству имен приложения:

namespace MauiBlazor;

Примечание.

В то время, когда KeypadViewModel модель представления была создана для .NET MAUI примера приложения и .NET MAUI документации, модели представления были помещены в папку с именем ViewModels, но пространство имен было установлено в корне приложения и не включало имя папки. Если вы хотите обновить пространство имен, чтобы включить папку в KeypadViewModel.cs файл, измените пример кода в этой статье на соответствие. Добавьте using операторы (C#) и @using (Razor) в следующие файлы или полностью квалифицируйте ссылки на тип модели представления как {APP NAMESPACE}.ViewModels.KeypadViewModel, где {APP NAMESPACE} заполнитель является корневым пространством имен приложения.

Хотя вы можете задать Parameters непосредственно в XAML, следующий пример называет корневой компонент (rootComponent) в XAML-файле и задает словарь параметров в файле кода программной части.

В MainPage.xaml:

<RootComponent x:Name="rootComponent" 
               Selector="#app" 
               ComponentType="{x:Type local:Main}" />

В файле программной части (MainPage.xaml.cs) назначьте модель представления в конструкторе:

public MainPage()
{
    InitializeComponent();

    rootComponent.Parameters = 
        new Dictionary<string, object>
        {
            { "KeypadViewModel", new KeypadViewModel() }
        };
}

Следующий пример каскадирует иерархии компонентов (KeypadViewModel) вниз в Blazor части приложения в виде.CascadingValue

В компоненте Main (Main.razor):

  • Добавьте параметр, соответствующий типу объекта, переданного корневому компоненту:

    @code {
        [Parameter]
        public KeypadViewModel KeypadViewModel { get; set; }
    }
    
  • Каскад с KeypadViewModel компонентомCascadingValue. Обновите содержимое XAML до следующей <Found> разметки:

    <Found Context="routeData">
        <CascadingValue Value="KeypadViewModel">
            <RouteView RouteData="routeData" DefaultLayout="typeof(MainLayout)" />
            <FocusOnNavigate RouteData="routeData" Selector="h1"/>
        </CascadingValue>
    </Found>
    

На этом этапе каскадный тип доступен Razor компонентам по всему приложению в качестве .CascadingParameter

Keypad Следующий пример компонента:

  • Отображает текущее значение KeypadViewModel.DisplayText.
  • Разрешает удаление символов путем вызова KeypadViewModel.DeleteCharCommand команды, если длина строки отображения превышает 0 (ноль), которая проверяется вызовом ICommand.CanExecute.
  • Разрешает добавлять символы, вызывая KeypadViewModel.AddCharCommand с помощью клавиши, нажатой в пользовательском интерфейсе.

Pages/Keypad.razor:

@page "/keypad"

<h1>Keypad</h1>

<table id="keypad">
    <thead>
        <tr>
            <th colspan="2">@KeypadViewModel.DisplayText</th>
            <th><button @onclick="DeleteChar">&#x21E6;</button></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><button @onclick="@(e => AddChar("1"))">1</button></td>
            <td><button @onclick="@(e => AddChar("2"))">2</button></td>
            <td><button @onclick="@(e => AddChar("3"))">3</button></td>
        </tr>
        <tr>
            <td><button @onclick="@(e => AddChar("4"))">4</button></td>
            <td><button @onclick="@(e => AddChar("5"))">5</button></td>
            <td><button @onclick="@(e => AddChar("6"))">6</button></td>
        </tr>
        <tr>
            <td><button @onclick="@(e => AddChar("7"))">7</button></td>
            <td><button @onclick="@(e => AddChar("8"))">8</button></td>
            <td><button @onclick="@(e => AddChar("9"))">9</button></td>
        </tr>
        <tr>
            <td><button @onclick="@(e => AddChar("*"))">*</button></td>
            <td><button @onclick="@(e => AddChar("0"))">0</button></td>
            <td><button @onclick="@(e => AddChar("#"))">#</button></td>
        </tr>
    </tbody>
</table>

@code {
    [CascadingParameter]
    protected KeypadViewModel KeypadViewModel { get; set; }

    private void DeleteChar()
    {
        if (KeypadViewModel.DeleteCharCommand.CanExecute(null))
        {
            KeypadViewModel.DeleteCharCommand.Execute(null);
        }
    }

    private void AddChar(string key)
    {
        KeypadViewModel.AddCharCommand.Execute(key);
    }
}

Исключительно для демонстрационных целей стиль кнопок путем размещения следующих стилей CSS в содержимом wwwroot/index.html файла <head> :

<style>
    #keypad button {
        border: 1px solid black;
        border-radius:6px;
        height: 35px;
        width:80px;
    }
</style>

Создайте запись навигации на боковой панели в компоненте NavMenu (Shared/NavMenu.razor) со следующей разметкой:

<div class="nav-item px-3">
    <NavLink class="nav-link" href="keypad">
        <span class="oi oi-list-rich" aria-hidden="true"></span> Keypad
    </NavLink>
</div>

Дополнительные ресурсы