在 ASP.NET Core Blazor Hybrid 中传递根组件参数
注意
此版本不是本文的最新版本。 对于当前版本,请参阅此文的 .NET 8 版本。
警告
此版本的 ASP.NET Core 不再受支持。 有关详细信息,请参阅 .NET 和 .NET Core 支持策略。 对于当前版本,请参阅此文的 .NET 8 版本。
本文介绍如何在 Blazor Hybrid 应用中传递根组件参数。
BlazorWebView
的 RootComponent
类定义 IDictionary<string, object?>?
类型的 Parameters
属性,该属性表示要传递给根组件的参数的可选字典:
- .NET MAUI: Microsoft.AspNetCore.Components.WebView.Maui.RootComponent
- WPF:Microsoft.AspNetCore.Components.WebView.Wpf.RootComponent
- Windows 窗体:Microsoft.AspNetCore.Components.WebView.WindowsForms.RootComponent
以下示例将一个视图模型传递给根组件,根组件进一步将视图模型作为级联类型传递给应用的 Blazor 部分中的 Razor 组件。 该示例基于 .NET MAUI 文档中的键盘示例:
- 数据绑定和 MVVM:命令(.NET MAUI 文档):使用键盘示例解释 MVVM 的数据绑定。
- .NET MAUI 示例
尽管键盘示例侧重于在 .NET MAUIBlazor Hybrid 应用中实现 MVVM 模式:
- 传递给根组件的对象的字典可以包含任何类型,用于需要将一个或多个参数传递给根组件,以供应用中的 Razor 组件使用的任何目的。
- 下面的 .NET MAUIBlazor 示例演示的概念对于 Windows 窗体 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;
注意
在为 .NET MAUI 示例应用和 .NET MAUI 文档创建 KeypadViewModel
视图模型时,视图模型放置在名为 ViewModels
的文件夹中,但命名空间设置为应用的根目录,未包含文件夹名称。 如果要更新命名空间以在 KeypadViewModel.cs
文件中包含改文件夹,请修改本文中的示例代码以进行匹配。 将 using
(C#) 和 @using
(Razor) 语句添加到以下文件中,或将对视图模型类型的引用完全限定为 {APP NAMESPACE}.ViewModels.KeypadViewModel
,其中 {APP NAMESPACE}
占位符是应用的根命名空间。
虽然可以直接在 XAML 中设置 Parameters
,但 XAML 文件中的以下示例为根组件命名 (rootComponent
),并在代码隐藏文件中设置参数字典。
在 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
) 作为 CascadingValue
在应用 Blazor 部分的组件层次结构中级联。
在 Main
组件 (Main.razor
) 中:
添加与传递给根组件的对象类型匹配的参数:
@code { [Parameter] public KeypadViewModel KeypadViewModel { get; set; } }
将
KeypadViewModel
与CascadingValue
组件级联。 将<Found>
XAML 内容更新为以下标记:<Found Context="routeData"> <CascadingValue Value="KeypadViewModel"> <RouteView RouteData="routeData" DefaultLayout="typeof(MainLayout)" /> <FocusOnNavigate RouteData="routeData" Selector="h1"/> </CascadingValue> </Found>
此时,级联类型作为 CascadingParameter
对整个应用中的 Razor 组件可用。
下面的 Keypad
组件示例:
- 显示
KeypadViewModel.DisplayText
的当前值。 - 在显示字符串长度大于 0(零)的情况下(通过调用 ICommand.CanExecute 来检查),允许通过调用
KeypadViewModel.DeleteCharCommand
命令来删除字符。 - 允许通过在 UI 中按下键,调用
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">⇦</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);
}
}
纯粹出于演示目的,通过在 wwwroot/index.html
文件的 <head>
内容中放置以下 CSS 样式来设置按钮的样式:
<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>
其他资源
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈