@page "/bind-after"
@using Microsoft.AspNetCore.Components.Forms
<h1>Bind After Examples</h1>
<h2>Elements</h2>
<input type="text" @bind="text" @bind:after="() => { }" />
<input type="text" @bind="text" @bind:after="After" />
<input type="text" @bind="text" @bind:after="AfterAsync" />
<h2>Components</h2>
<InputText @bind-Value="text" @bind-Value:after="() => { }" />
<InputText @bind-Value="text" @bind-Value:after="After" />
<InputText @bind-Value="text" @bind-Value:after="AfterAsync" />
@code {
private string text = "";
private void After() {}
private Task AfterAsync() { return Task.CompletedTask; }
有关 InputText
组件的详细信息,请参阅《ASP.NET Core Blazor 输入组件》。
组件通过定义一对参数来支持双向数据绑定:
@bind:get
:指定要绑定的值。
@bind:set
:指定值更改时的回调。
@bind:get
和 @bind:set
修饰符始终一起使用。
不支持结合使用事件回调参数和 @bind:set
([Parameter] public EventCallback<string> ValueChanged { get; set; }
)。 相反,将返回 Action 或 Task 的方法传递给 @bind:set
。
BindGetSet.razor
:
@page "/bind-get-set"
@using Microsoft.AspNetCore.Components.Forms
<h1>Bind Get Set Examples</h1>
<h2>Elements</h2>
<input type="text" @bind:get="text" @bind:set="(value) => { text = value; }" />
<input type="text" @bind:get="text" @bind:set="Set" />
<input type="text" @bind:get="text" @bind:set="SetAsync" />
<h2>Components</h2>
<InputText @bind-Value:get="text" @bind-Value:set="(value) => { text = value; }" />
<InputText @bind-Value:get="text" @bind-Value:set="Set" />
<InputText @bind-Value:get="text" @bind-Value:set="SetAsync" />
@code {
private string text = "";
private void Set(string value)
text = value;
private Task SetAsync(string value)
text = value;
return Task.CompletedTask;
有关 InputText
组件的详细信息,请参阅《ASP.NET Core Blazor 输入组件》。
有关使用 @bind:get
和 @bind:set
的另一个示例,请参阅本文后面绑定到两个以上的组件部分。
Razor 属性绑定区分大小写:
@bind
、@bind:event
和 @bind:after
有效。
@Bind
/@bind:Event
/@bind:aftEr
(大写字母)或 @BIND
/@BIND:EVENT
/@BIND:AFTER
(全部是大写字母)无效。
使用 @bind:get
/@bind:set
修饰符并避免使用事件处理程序进行双向数据绑定
双向数据绑定是不能使用事件处理程序实现的。 需要使用 @bind:get
/@bind:set
修饰符进行双向数据绑定。
❌ 来看看下面使用事件处理程序进行双向数据绑定的一种失效性方法:
<input value="@inputValue" @oninput="OnInput" />
<code>inputValue</code>: @inputValue
@code {
private string? inputValue;
private void OnInput(ChangeEventArgs args)
var newValue = args.Value?.ToString() ?? string.Empty;
inputValue = newValue.Length > 4 ? "Long!" : newValue;
在提供第四个字符后,OnInput
事件处理程序将 inputValue
的值更新为 Long!
。 但是,用户可以继续在 UI 中向元素值添加字符。 inputValue
的值并没有随着每次击键而绑定回元素的值。 前面的示例只能进行单向数据绑定。
此行为的原因是,Blazor 不知道代码打算在事件处理程序中修改 inputValue
的值。 Blazor 不会尝试强制 DOM 元素值和 .NET 变量值进行匹配,除非它们通过 @bind
语法绑定。 在 Blazor 的早期版本中,双向数据绑定是通过将元素绑定到属性并使用其资源库控制属性的值实现的。 在 ASP.NET Core 7.0 或更高版本中,@bind:get
/@bind:set
修饰符语法用于实现双向数据绑定,如下一示例所示。
✔️ 来看看下面使用 @bind:get
/@bind:set
进行双向数据绑定的正确方法:
<input @bind:event="oninput" @bind:get="inputValue" @bind:set="OnInput" />
<code>inputValue</code>: @inputValue
@code {
private string? inputValue;
private void OnInput(string value)
var newValue = value ?? string.Empty;
inputValue = newValue.Length > 4 ? "Long!" : newValue;
使用 @bind:get
/@bind:set
修饰符,既能通过 @bind:set
控制 inputValue
的基础值,又能通过 @bind:get
将 inputValue
的值绑定到元素的值。 前面的示例演示了实现双向数据绑定的正确方法。
使用 C# get
和 set
访问器绑定到属性
C# get
和 set
访问器可用于创建自定义绑定格式行为,如下面的 DecimalBinding
组件所示。 此组件通过 string
属性 (DecimalValue
) 将最多具有三个小数位的正或负小数伪绑定到 <input>
元素。
DecimalBinding.razor
:
@page "/decimal-binding"
@using System.Globalization
<label>
Decimal value (±0.000 format):
<input @bind="DecimalValue" />
</label>
<code>decimalValue</code>: @decimalValue
@code {
private decimal decimalValue = 1.1M;
private NumberStyles style =
NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign;
private CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
private string DecimalValue
get => decimalValue.ToString("0.000", culture);
if (Decimal.TryParse(value, style, culture, out var number))
decimalValue = Math.Round(number, 3);
private decimal decimalValue = 1.1M;
private NumberStyles style =
NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign;
private CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
private string DecimalValue
get => decimalValue.ToString("0.000", culture);
if (Decimal.TryParse(value, style, culture, out var number))
decimalValue = Math.Round(number, 3);
private decimal decimalValue = 1.1M;
private NumberStyles style =
NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign;
private CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
private string DecimalValue
get => decimalValue.ToString("0.000", culture);
if (Decimal.TryParse(value, style, culture, out var number))
decimalValue = Math.Round(number, 3);
private decimal decimalValue = 1.1M;
private NumberStyles style =
NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign;
private CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
private string DecimalValue
get => decimalValue.ToString("0.000", culture);
if (Decimal.TryParse(value, style, culture, out var number))
decimalValue = Math.Round(number, 3);
使用 <select>
元素的多个选项选择
绑定支持使用 <select>
元素的 multiple
选项选择。 @onchange
事件通过事件参数 (ChangeEventArgs
) 提供一个选定元素的数组。 值必须绑定到数组类型。
BindMultipleInput.razor
:
@page "/bind-multiple-input"
<h1>Bind Multiple <code>input</code>Example</h1>
<label>
Select one or more cars:
<select @onchange="SelectedCarsChanged" multiple>
<option value="audi">Audi</option>
<option value="jeep">Jeep</option>
<option value="opel">Opel</option>
<option value="saab">Saab</option>
<option value="volvo">Volvo</option>
</select>
</label>
Selected Cars: @string.Join(", ", SelectedCars)
<label>
Select one or more cities:
<select @bind="SelectedCities" multiple>
<option value="bal">Baltimore</option>
<option value="la">Los Angeles</option>
<option value="pdx">Portland</option>
<option value="sf">San Francisco</option>
<option value="sea">Seattle</option>
</select>
</label>
Selected Cities: @string.Join(", ", SelectedCities)
</span>
@code {
public string[] SelectedCars { get; set; } = new string[] { };
public string[] SelectedCities { get; set; } = new[] { "bal", "sea" };
private void SelectedCarsChanged(ChangeEventArgs e)
if (e.Value is not null)
SelectedCars = (string[])e.Value;
有关如何在数据绑定中处理空字符串和 null
值的信息,请参阅将 <select>
元素绑定到 C# 对象 null
值部分。
将 <select>
元素选项绑定到 C# 对象 null
值
由于以下原因,没有将 <select>
元素选项值表示为 C# 对象 null
值的合理方法:
HTML 属性不能具有 null
值。 HTML 中最接近的 null
等效项是 <option>
元素中缺少 HTML value
属性。
选择没有 value
属性的 <option>
时,浏览器会将值视为该 <option>
的元素的 文本内容。
Blazor 框架不会尝试取消默认行为,因为这会涉及以下操作:
在框架中创建一系列特殊的解决办法。
对当前框架行为进行重大更改。
HTML 中最合理的 null
等效项是空字符串value
。 Blazor 框架处理 null
到空字符串之间的转换,以便双向绑定到 <select>
的值。
无法分析的值
如果用户向数据绑定元素提供无法分析的值,则在触发绑定事件时,无法分析的值会自动还原为以前的值。
以下面的组件为例,其中 <input>
元素绑定到初始值为 123
的 int
类型。
UnparsableValues.razor
:
@page "/unparseable-values"
<input @bind="inputValue" />
<code>inputValue</code>: @inputValue
@code {
private int inputValue = 123;
默认情况下,绑定适用于元素的 onchange
事件。 如果用户将文本框输入的值更新为 123.45
并更改焦点,则元素的值将在 onchange
触发时还原为 123
。 如果拒绝值 123.45
以采用原始值 123
,则用户会了解其值不被接受。
对于 oninput
事件 (@bind:event="oninput"
),将在执行生成无法分析的值的击键操作后还原值。 当使用 int
绑定类型以 oninput
事件为目标时,会阻止用户键入小数点 (.
) 字符。 小数点 (.
) 字符会立即被删除,因此用户会收到仅允许整数的即时反馈。 在某些情况下,在 oninput
事件中还原值并不理想,例如在应该允许用户清除无法解析的 <input>
值时。 替代方案包括:
不使用 oninput
事件。 使用默认 onchange
事件,其中无效值在元素失去焦点之前不会还原。
绑定到一个可以为 null 的类型(如 int?
或 string
),并使用 @bind:get
/@bind:set
修饰符(如本文前面所述)或使用自定义 get
和 set
访问器逻辑绑定到属性来处理无效输入。
使用窗体验证组件,如 InputNumber<TValue> 或 InputDate<TValue>。 窗体验证组件提供用于管理无效输入的内置支持。 窗体验证组件:
- 允许用户提供无效输入并在关联的 EditContext 上接收验证错误。
- 在 UI 中显示验证错误,而不干扰用户输入其他 webform 数据。
数据绑定通过 @bind:format="{FORMAT STRING}"
使用单个 DateTime 格式字符串,其中 {FORMAT STRING}
占位符是格式字符串。 其他格式表达式(如货币或数字格式)目前不可用,但可能会在将来的版本中添加。
DateBinding.razor
:
@page "/date-binding"
<label>
<code>yyyy-MM-dd</code> format:
<input @bind="startDate" @bind:format="yyyy-MM-dd" />
</label>
<code>startDate</code>: @startDate
@code {
private DateTime startDate = new(2020, 1, 1);
在前面的代码中,<input>
元素的字段类型(type
特性)默认为 text
。
支持可为 null 的 System.DateTime 和 System.DateTimeOffset:
private DateTime? date;
private DateTimeOffset? dateOffset;
不建议为 date
字段类型指定格式,因为 Blazor 具有用于设置日期格式的内置支持。 尽管提出了建议,但如果使用 date
字段类型提供格式,则只有使用 yyyy-MM-dd
日期格式才能使绑定正常工作:
<input type="date" @bind="startDate" @bind:format="yyyy-MM-dd">
与组件参数绑定
常见方案是将子组件中的属性绑定到其父组件中的属性。 此方案称为链接绑定,因为多个级别的绑定会同时进行。
组件参数允许使用 @bind-{PROPERTY}
语法绑定父组件的属性,其中 {PROPERTY}
占位符是要绑定的属性。
不能在子组件中使用 @bind
语法来实现链接绑定。 必须单独指定事件处理程序和值,以支持从子组件更新父组件中的属性。
父组件仍利用 @bind
语法来设置与子组件的数据绑定。
以下 ChildBind
组件具有 Year
组件参数和 EventCallback<TValue>。 按照约定,此参数的 EventCallback<TValue> 必须以组件参数名称命名,并带有“Changed
”后缀。 命名语法为 {PARAMETER NAME}Changed
,其中 {PARAMETER NAME}
占位符是参数名称。 在以下示例中,将 EventCallback<TValue> 命名为 YearChanged
。
EventCallback.InvokeAsync 调用与提供的参数进行绑定相关联的委托,并为已更改的属性调度事件通知。
ChildBind.razor
:
<div class="card bg-light mt-3" style="width:18rem ">
<div class="card-body">
<h3 class="card-title">ChildBind Component</h3>
<p class="card-text">
Child <code>Year</code>: @Year
<button @onclick="UpdateYearFromChild">Update Year from Child</button>
@code {
private Random r = new();
[Parameter]
public int Year { get; set; }
[Parameter]
public EventCallback<int> YearChanged { get; set; }
private async Task UpdateYearFromChild()
await YearChanged.InvokeAsync(r.Next(1950, 2021));
<div class="card bg-light mt-3" style="width:18rem ">
<div class="card-body">
<h3 class="card-title">ChildBind Component</h3>
<p class="card-text">
Child <code>Year</code>: @Year
<button @onclick="UpdateYearFromChild">Update Year from Child</button>
@code {
private Random r = new();
[Parameter]
public int Year { get; set; }
[Parameter]
public EventCallback<int> YearChanged { get; set; }
private async Task UpdateYearFromChild()
await YearChanged.InvokeAsync(r.Next(1950, 2021));
<div class="card bg-light mt-3" style="width:18rem ">
<div class="card-body">
<h3 class="card-title">ChildBind Component</h3>
<p class="card-text">
Child <code>Year</code>: @Year
<button @onclick="UpdateYearFromChild">Update Year from Child</button>
@code {
private Random r = new();
[Parameter]
public int Year { get; set; }
[Parameter]
public EventCallback<int> YearChanged { get; set; }
private async Task UpdateYearFromChild()
await YearChanged.InvokeAsync(r.Next(1950, 2021));
<div class="card bg-light mt-3" style="width:18rem ">
<div class="card-body">
<h3 class="card-title">ChildBind Component</h3>
<p class="card-text">
Child <code>Year</code>: @Year
<button @onclick="UpdateYearFromChild">Update Year from Child</button>
@code {
private Random r = new Random();
[Parameter]
public int Year { get; set; }
[Parameter]
public EventCallback<int> YearChanged { get; set; }
private async Task UpdateYearFromChild()
await YearChanged.InvokeAsync(r.Next(1950, 2021));
有关事件和 EventCallback<TValue> 的详细信息,请参阅 ASP.NET Core Blazor 事件处理一文的“EventCallback”部分。
在下面的 Parent1
组件中,Year
字段绑定到子组件的 year
参数。 Year
参数是可绑定的,因为它具有与 Year
参数类型相匹配的伴随 YearChanged
事件。
Parent1.razor
:
@page "/parent-1"
<h1>Parent Component</h1>
<p>Parent <code>year</code>: @year</p>
<button @onclick="UpdateYear">Update Parent <code>year</code></button>
<ChildBind @bind-Year="year" />
@code {
private Random r = new();
private int year = 1979;
private void UpdateYear()
year = r.Next(1950, 2021);
<p>Parent <code>year</code>: @year</p>
<button @onclick="UpdateYear">Update Parent <code>year</code></button>
<ChildBind @bind-Year="year" />
@code {
private Random r = new();
private int year = 1979;
private void UpdateYear()
year = r.Next(1950, 2021);
<p>Parent <code>year</code>: @year</p>
<button @onclick="UpdateYear">Update Parent <code>year</code></button>
<ChildBind @bind-Year="year" />
@code {
private Random r = new();
private int year = 1979;
private void UpdateYear()
year = r.Next(1950, 2021);
<p>Parent <code>year</code>: @year</p>
<button @onclick="UpdateYear">Update Parent <code>year</code></button>
<ChildBind @bind-Year="year" />
@code {
private Random r = new Random();
private int year = 1979;
private void UpdateYear()
year = r.Next(1950, 2021);
组件参数绑定还可以触发 @bind:after
事件。 在以下示例中,YearUpdated
方法在绑定 Year
组件参数后以异步方式执行。
<ChildBind @bind-Year="year" @bind-Year:after="YearUpdated" />
@code {
private async Task YearUpdated()
... = await ...;
按照约定,可通过包含分配到处理程序的 @bind-{PROPERTY}:event
特性,将属性绑定到对应的事件处理程序,其中 {PROPERTY}
占位符是属性。 <ChildBind @bind-Year="year" />
等效于此写入:
<ChildBind @bind-Year="year" @bind-Year:event="YearChanged" />
在更复杂和实际的示例中,以下 PasswordEntry
组件:
- 将
<input>
元素的值设置为 password
字段。
- 将
Password
属性的更改公开给父组件,其中 EventCallback
以子级 password
字段的当前值作为参数传递。
- 使用
onclick
事件触发 ToggleShowPassword
方法。 有关详细信息,请参阅 ASP.NET Core Blazor 事件处理。
PasswordEntry.razor
:
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged"
required
type="@(showPassword ? "text" : "password")"
value="@password" />
</label>
<button class="btn btn-primary" @onclick="ToggleShowPassword">
Show password
</button>
@code {
private bool showPassword;
private string? password;
[Parameter]
public string? Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private async Task OnPasswordChanged(ChangeEventArgs e)
password = e?.Value?.ToString();
await PasswordChanged.InvokeAsync(password);
private void ToggleShowPassword()
showPassword = !showPassword;
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged"
required
type="@(showPassword ? "text" : "password")"
value="@password" />
</label>
<button class="btn btn-primary" @onclick="ToggleShowPassword">
Show password
</button>
@code {
private bool showPassword;
private string? password;
[Parameter]
public string? Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private async Task OnPasswordChanged(ChangeEventArgs e)
password = e?.Value?.ToString();
await PasswordChanged.InvokeAsync(password);
private void ToggleShowPassword()
showPassword = !showPassword;
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged"
required
type="@(showPassword ? "text" : "password")"
value="@password" />
</label>
<button class="btn btn-primary" @onclick="ToggleShowPassword">
Show password
</button>
@code {
private bool showPassword;
private string password;
[Parameter]
public string Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private async Task OnPasswordChanged(ChangeEventArgs e)
password = e.Value.ToString();
await PasswordChanged.InvokeAsync(password);
private void ToggleShowPassword()
showPassword = !showPassword;
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged"
required
type="@(showPassword ? "text" : "password")"
value="@password" />
</label>
<button class="btn btn-primary" @onclick="ToggleShowPassword">
Show password
</button>
@code {
private bool showPassword;
private string password;
[Parameter]
public string Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private async Task OnPasswordChanged(ChangeEventArgs e)
password = e.Value.ToString();
await PasswordChanged.InvokeAsync(password);
private void ToggleShowPassword()
showPassword = !showPassword;
PasswordEntry
组件用于另一个组件中,例如下面的 PasswordBinding
组件示例。
PasswordBinding.razor
:
@page "/password-binding"
<h1>Password Binding</h1>
<PasswordEntry @bind-Password="password" />
<code>password</code>: @password
@code {
private string password = "Not set";
最初呈现 PasswordBinding
组件时,在 UI 中显示 Not set
的 password
值。 初始呈现后,password
的值反映对 PasswordEntry
组件中的 Password
组件参数值所做的更改。
前面的示例将密码从子 PasswordEntry
组件单向绑定到父 PasswordBinding
组件。 如果目标是让应用具有共享密码输入组件以供周围仅将密码传递给父级的应用重复使用,那么在这种情况下并不要求双向绑定。 有关在不直接写入子组件的参数的情况下允许进行双向绑定的方法,请参阅本文的绑定到两个以上的组件部分中的 NestedChild
组件示例。
在处理程序中执行检查或捕获错误。 经过修改的以下 PasswordEntry
组件会在密码的值中使用空格时向用户提供即时反馈。
PasswordEntry.razor
:
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged"
required
type="@(showPassword ? "text" : "password")"
value="@password" />
</label>
<span class="text-danger">@validationMessage</span>
<button class="btn btn-primary" @onclick="ToggleShowPassword">
Show password
</button>
@code {
private bool showPassword;
private string? password;
private string? validationMessage;
[Parameter]
public string? Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private Task OnPasswordChanged(ChangeEventArgs e)
password = e?.Value?.ToString();
if (password != null && password.Contains(' '))
validationMessage = "Spaces not allowed!";
return Task.CompletedTask;
validationMessage = string.Empty;
return PasswordChanged.InvokeAsync(password);
private void ToggleShowPassword()
showPassword = !showPassword;
在以下示例中,PasswordUpdated
方法在绑定 Password
组件参数后以异步方式执行:
<PasswordEntry @bind-Password="password" @bind-Password:after="PasswordUpdated" />
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged"
required
type="@(showPassword ? "text" : "password")"
value="@password" />
</label>
<span class="text-danger">@validationMessage</span>
<button class="btn btn-primary" @onclick="ToggleShowPassword">
Show password
</button>
@code {
private bool showPassword;
private string? password;
private string? validationMessage;
[Parameter]
public string? Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private Task OnPasswordChanged(ChangeEventArgs e)
password = e?.Value?.ToString();
if (password != null && password.Contains(' '))
validationMessage = "Spaces not allowed!";
return Task.CompletedTask;
validationMessage = string.Empty;
return PasswordChanged.InvokeAsync(password);
private void ToggleShowPassword()
showPassword = !showPassword;
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged"
required
type="@(showPassword ? "text" : "password")"
value="@password" />
</label>
<span class="text-danger">@validationMessage</span>
<button class="btn btn-primary" @onclick="ToggleShowPassword">
Show password
</button>
@code {
private bool showPassword;
private string password;
private string validationMessage;
[Parameter]
public string Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private Task OnPasswordChanged(ChangeEventArgs e)
password = e.Value.ToString();
if (password.Contains(' '))
validationMessage = "Spaces not allowed!";
return Task.CompletedTask;
validationMessage = string.Empty;
return PasswordChanged.InvokeAsync(password);
private void ToggleShowPassword()
showPassword = !showPassword;
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged"
required
type="@(showPassword ? "text" : "password")"
value="@password" />
</label>
<span class="text-danger">@validationMessage</span>
<button class="btn btn-primary" @onclick="ToggleShowPassword">
Show password
</button>
@code {
private bool showPassword;
private string password;
private string validationMessage;
[Parameter]
public string Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private Task OnPasswordChanged(ChangeEventArgs e)
password = e.Value.ToString();
if (password.Contains(' '))
validationMessage = "Spaces not allowed!";
return Task.CompletedTask;
validationMessage = string.Empty;
return PasswordChanged.InvokeAsync(password);
private void ToggleShowPassword()
showPassword = !showPassword;
绑定到两个以上的组件
可以将参数绑定到任意数量的嵌套组件,但必须采用单向数据流:
- 更改通知沿层次结构向上传递。
- 新参数值按层次结构向下传递。
推荐的常见方法是仅将基础数据存储在父组件中,以避免对必须更新的状态产生任何混淆,如下面示例所示。
Parent2.razor
:
@page "/parent-2"
<h1>Parent Component</h1>
<p>Parent Message: <b>@parentMessage</b></p>
<button @onclick="ChangeValue">Change from Parent</button>
<NestedChild @bind-ChildMessage="parentMessage" />
@code {
private string parentMessage = "Initial value set in Parent";
private void ChangeValue()
parentMessage = $"Set in Parent {DateTime.Now}";
在下面的 NestedChild
组件中,NestedGrandchild
组件:
- 使用
@bind:get
语法将 ChildMessage
的值分配给 GrandchildMessage
。
- 当
ChildMessageChanged
使用 @bind:set
语法执行时更新 GrandchildMessage
。
NestedChild.razor
:
<div class="border rounded m-1 p-1">
<h2>Child Component</h2>
<p>Child Message: <b>@ChildMessage</b></p>
<button @onclick="ChangeValue">Change from Child</button>
<NestedGrandchild @bind-GrandchildMessage:get="ChildMessage"
@bind-GrandchildMessage:set="ChildMessageChanged" />
@code {
[Parameter]
public string? ChildMessage { get; set; }
[Parameter]
public EventCallback<string> ChildMessageChanged { get; set; }
private async Task ChangeValue()
await ChildMessageChanged.InvokeAsync(
$"Set in Child {DateTime.Now}");
一般来说,避免创建直接向自己的组件参数写入的组件。 前面的 NestedChild
组件使用 BoundValue
属性,而不是直接写入其 ChildMessage
参数。 有关详细信息,请参阅避免覆盖 ASP.NET Core Blazor 中的参数。
NestedGrandchild.razor
:
<div class="border rounded m-1 p-1">
<h3>Grandchild Component</h3>
<p>Grandchild Message: <b>@GrandchildMessage</b></p>
<button @onclick="ChangeValue">Change from Grandchild</button>
@code {
[Parameter]
public string? GrandchildMessage { get; set; }
[Parameter]
public EventCallback<string> GrandchildMessageChanged { get; set; }
private async Task ChangeValue()
await GrandchildMessageChanged.InvokeAsync(
$"Set in Grandchild {DateTime.Now}");
public EventCallback<string> GrandchildMessageChanged { get; set; }
private async Task ChangeValue()
await GrandchildMessageChanged.InvokeAsync(
$"Set in Grandchild {DateTime.Now}");
public EventCallback<string> GrandchildMessageChanged { get; set; }
private async Task ChangeValue()
await GrandchildMessageChanged.InvokeAsync(
$"Set in Grandchild {DateTime.Now}");
public EventCallback<string> GrandchildMessageChanged { get; set; }
private async Task ChangeValue()
await GrandchildMessageChanged.InvokeAsync(
$"Set in Grandchild {DateTime.Now}");
有关适用于在内存中和跨不必嵌套的组件共享数据的替代方法,请参阅 ASP.NET Core Blazor 状态管理。
- 有关 Razor 组件呈现的参数更改检测和其他指南
- ASP.NET Core Blazor 窗体概述
- 绑定到窗体中的单选按钮
- 将
InputSelect
选项绑定到 C# 对象 null
值
- ASP.NET Core Blazor 事件处理:
EventCallback
部分
- Blazor 示例 GitHub 存储库 (
dotnet/blazor-samples
)