ASP.NET Core Blazor 表單繫結
注意
這不是這篇文章的最新版本。 如需目前的版本,請參閱 本文的 .NET 9 版本。
警告
不再支援此版本的 ASP.NET Core。 如需詳細資訊,請參閱 .NET 和 .NET Core 支援原則。 如需目前版本,請參閱本文的 .NET 8 版本。
本文說明如何在 Blazor 表單中使用繫結。
EditForm
/EditContext
模型
EditForm 會根據指派的物件建立 EditContext,做為表單中其他元件的串聯值。 EditContext 會追蹤有關編輯程序的中繼資料,包括哪些表單欄位已修改和目前的驗證訊息。 指派給 EditForm.Model 或 EditForm.EditContext 可以將表單繫結至資料。
模型繫結
指派給 EditForm.Model:
<EditForm ... Model="Model" ...>
...
</EditForm>
@code {
[SupplyParameterFromForm]
private Starship? Model { get; set; }
protected override void OnInitialized() => Model ??= new();
}
<EditForm ... Model="Model" ...>
...
</EditForm>
@code {
public Starship? Model { get; set; }
protected override void OnInitialized() => Model ??= new();
}
注意
本文的大部分表單模型範例會將表單繫結至 C# 屬性,但也支援 C# 欄位繫結。
內容繫結
指派給 EditForm.EditContext:
<EditForm ... EditContext="editContext" ...>
...
</EditForm>
@code {
private EditContext? editContext;
[SupplyParameterFromForm]
private Starship? Model { get; set; }
protected override void OnInitialized()
{
Model ??= new();
editContext = new(Model);
}
}
<EditForm ... EditContext="editContext" ...>
...
</EditForm>
@code {
private EditContext? editContext;
public Starship? Model { get; set; }
protected override void OnInitialized()
{
Model ??= new();
editContext = new(Model);
}
}
將 EditContext 或 Model 之一指派給 EditForm。 如果同時指派兩者,則會擲出執行階段錯誤。
支援的類型
繫結支援:
- 基本類型
- 集合
- 複雜類型
- 遞迴型別
- 具有建構函式的型別
- 列舉
您也可以使用 [DataMember]
和 [IgnoreDataMember]
屬性來自訂模型繫結。 使用這些屬性來重新命名屬性、忽略屬性,以及視需要標記屬性。
其他繫結選項
呼叫 AddRazorComponents 時,可從 RazorComponentsServiceOptions 取得其他模型繫結選項:
- MaxFormMappingCollectionSize:表單集合中允許的元素數目上限。
- MaxFormMappingRecursionDepth:遞迴對應表單資料時允許的最大深度。
- MaxFormMappingErrorCount:對應表單資料時允許的錯誤數目上限。
- MaxFormMappingKeySize:用來讀取表單資料索引鍵的緩衝區大小上限。
以下示範架構指派的預設值:
builder.Services.AddRazorComponents(options =>
{
options.FormMappingUseCurrentCulture = true;
options.MaxFormMappingCollectionSize = 1024;
options.MaxFormMappingErrorCount = 200;
options.MaxFormMappingKeySize = 1024 * 2;
options.MaxFormMappingRecursionDepth = 64;
}).AddInteractiveServerComponents();
表單名稱
使用 FormName 參數來指派表單名稱。 表單名稱必須是唯一的,才能繫結模型資料。 下列表單名為 RomulanAle
:
<EditForm ... FormName="RomulanAle" ...>
...
</EditForm>
提供表單名稱:
- 所有由靜態轉譯的伺服器端元件提交的表單都需要。
- 對於以互動方式轉譯的元件所提交的表單並非必要,其中包括 Blazor WebAssembly 應用程式中的表單和具有互動式轉譯模式的元件。 不過,我們建議為每個表單提供唯一的表單名稱,以避免在表單的互動功能遭到捨棄時發生執行階段表單張貼錯誤。
只有在表單以傳統 HTTP POST 要求的形式 (來自靜態轉譯的伺服器端元件) 張貼到端點時,才會檢查表單名稱。 架構不會在轉譯表單時擲出例外狀況,而是只會在 HTTP POST 到達且未指定表單名稱時擲出例外狀況。
應用程式的根元件上方有一個未命名的 (空字串) 表單範圍,當應用程式中沒有表單名稱衝突時,此範圍就已足夠。 若有可能發生表單名稱衝突,(例如,若您納入某個程式庫中的表單,但無權控制程式庫開發人員所使用的表單名稱),請為 Blazor Web App 主要專案中的 FormMappingScope 元件提供表單名稱範圍。
在下列範例中,HelloFormFromLibrary
元件具有名為 Hello
的表單,且位於程式庫中。
HelloFormFromLibrary.razor
:
<EditForm FormName="Hello" Model="this" OnSubmit="Submit">
<InputText @bind-Value="Name" />
<button type="submit">Submit</button>
</EditForm>
@if (submitted)
{
<p>Hello @Name from the library's form!</p>
}
@code {
bool submitted = false;
[SupplyParameterFromForm]
private string? Name { get; set; }
private void Submit() => submitted = true;
}
下列 NamedFormsWithScope
元件會使用程式庫的 HelloFormFromLibrary
元件,而且也有名為 Hello
的表單。 對於 HelloFormFromLibrary
元件所提供的任何表單,FormMappingScope 元件的範圍名稱皆為 ParentContext
。 雖然此範例中的兩個表單都有表單名稱 (Hello
),但這些表單名稱並未衝突,且事件會路由至表單 POST 事件的正確表單。
NamedFormsWithScope.razor
:
@page "/named-forms-with-scope"
<div>Hello form from a library</div>
<FormMappingScope Name="ParentContext">
<HelloFormFromLibrary />
</FormMappingScope>
<div>Hello form using the same form name</div>
<EditForm FormName="Hello" Model="this" OnSubmit="Submit">
<InputText @bind-Value="Name" />
<button type="submit">Submit</button>
</EditForm>
@if (submitted)
{
<p>Hello @Name from the app form!</p>
}
@code {
bool submitted = false;
[SupplyParameterFromForm]
private string? Name { get; set; }
private void Submit() => submitted = true;
}
從表單提供參數 ([SupplyParameterFromForm]
)
[SupplyParameterFromForm]
屬性會指出應該從表單的表單資料提供相關聯屬性的值。 要求中符合屬性名稱的資料會繫結至屬性。 根據 InputBase<TValue>
的輸入會產生符合 Blazor 用於模型繫結名稱的表單值名稱。 不同於元件參數屬性 ([Parameter]
), 使用 [SupplyParameterFromForm]
附註的屬性不需要標示為 public
。
您可以將下列表單繫結參數指定給 [SupplyParameterFromForm]
屬性:
- Name:取得或設定參數的名稱。 該名稱會用來判斷要用來比對表單資料的前置詞,以及決定是否需要繫結值。
- FormName:取得或設定處理常式的名稱。 該名稱會用來依表單名稱比對表單的參數,以決定是否需要繫結值。
下列範例會依表單名稱,將兩個表單獨立繫結至其模型。
Starship6.razor
:
@page "/starship-6"
@inject ILogger<Starship6> Logger
<EditForm Model="Model1" OnSubmit="Submit1" FormName="Holodeck1">
<div>
<label>
Holodeck 1 Identifier:
<InputText @bind-Value="Model1!.Id" />
</label>
</div>
<div>
<button type="submit">Submit</button>
</div>
</EditForm>
<EditForm Model="Model2" OnSubmit="Submit2" FormName="Holodeck2">
<div>
<label>
Holodeck 2 Identifier:
<InputText @bind-Value="Model2!.Id" />
</label>
</div>
<div>
<button type="submit">Submit</button>
</div>
</EditForm>
@code {
[SupplyParameterFromForm(FormName = "Holodeck1")]
private Holodeck? Model1 { get; set; }
[SupplyParameterFromForm(FormName = "Holodeck2")]
private Holodeck? Model2 { get; set; }
protected override void OnInitialized()
{
Model1 ??= new();
Model2 ??= new();
}
private void Submit1() => Logger.LogInformation("Submit1: Id={Id}", Model1?.Id);
private void Submit2() => Logger.LogInformation("Submit2: Id={Id}", Model2?.Id);
public class Holodeck
{
public string? Id { get; set; }
}
}
@page "/starship-6"
@inject ILogger<Starship6> Logger
<EditForm Model="Model1" OnSubmit="Submit1" FormName="Holodeck1">
<div>
<label>
Holodeck 1 Identifier:
<InputText @bind-Value="Model1!.Id" />
</label>
</div>
<div>
<button type="submit">Submit</button>
</div>
</EditForm>
<EditForm Model="Model2" OnSubmit="Submit2" FormName="Holodeck2">
<div>
<label>
Holodeck 2 Identifier:
<InputText @bind-Value="Model2!.Id" />
</label>
</div>
<div>
<button type="submit">Submit</button>
</div>
</EditForm>
@code {
[SupplyParameterFromForm(FormName = "Holodeck1")]
private Holodeck? Model1 { get; set; }
[SupplyParameterFromForm(FormName = "Holodeck2")]
private Holodeck? Model2 { get; set; }
protected override void OnInitialized()
{
Model1 ??= new();
Model2 ??= new();
}
private void Submit1() => Logger.LogInformation("Submit1: Id={Id}", Model1?.Id);
private void Submit2() => Logger.LogInformation("Submit2: Id={Id}", Model2?.Id);
public class Holodeck
{
public string? Id { get; set; }
}
}
巢狀和繫結表單
下列指導示範如何為子表單建立巢狀和繫結。
下列飛船詳細資料類別 (ShipDetails
) 會保存子表單的描述和長度。
ShipDetails.cs
:
namespace BlazorSample;
public class ShipDetails
{
public string? Description { get; set; }
public int? Length { get; set; }
}
namespace BlazorSample;
public class ShipDetails
{
public string? Description { get; set; }
public int? Length { get; set; }
}
下列 Ship
類別會命名識別碼 (Id
),並包含飛船詳細資料。
Ship.cs
:
namespace BlazorSample
{
public class Ship
{
public string? Id { get; set; }
public ShipDetails Details { get; set; } = new();
}
}
namespace BlazorSample
{
public class Ship
{
public string? Id { get; set; }
public ShipDetails Details { get; set; } = new();
}
}
下列子表單用於編輯 ShipDetails
型別的值。 這是藉由在元件頂端繼承 Editor<T> 來實作。 Editor<T> 可確保子元件會根據模型產生正確的表單欄位名稱 (T
),其中 T
在下列範例中為 ShipDetails
。
StarshipSubform.razor
:
@inherits Editor<ShipDetails>
<div>
<label>
Description:
<InputText @bind-Value="Value!.Description" />
</label>
</div>
<div>
<label>
Length:
<InputNumber @bind-Value="Value!.Length" />
</label>
</div>
@inherits Editor<ShipDetails>
<div>
<label>
Description:
<InputText @bind-Value="Value!.Description" />
</label>
</div>
<div>
<label>
Length:
<InputNumber @bind-Value="Value!.Length" />
</label>
</div>
主要表單會繫結至 Ship
類別。 StarshipSubform
元件會用來編輯飛船詳細資料,繫結為 Model!.Details
。
Starship7.razor
:
@page "/starship-7"
@inject ILogger<Starship7> Logger
<EditForm Model="Model" OnSubmit="Submit" FormName="Starship7">
<div>
<label>
Identifier:
<InputText @bind-Value="Model!.Id" />
</label>
</div>
<StarshipSubform @bind-Value="Model!.Details" />
<div>
<button type="submit">Submit</button>
</div>
</EditForm>
@code {
[SupplyParameterFromForm]
private Ship? Model { get; set; }
protected override void OnInitialized() => Model ??= new();
private void Submit() =>
Logger.LogInformation("Id = {Id} Desc = {Description} Length = {Length}",
Model?.Id, Model?.Details?.Description, Model?.Details?.Length);
}
@page "/starship-7"
@inject ILogger<Starship7> Logger
<EditForm Model="Model" OnSubmit="Submit" FormName="Starship7">
<div>
<label>
Identifier:
<InputText @bind-Value="Model!.Id" />
</label>
</div>
<StarshipSubform @bind-Value="Model!.Details" />
<div>
<button type="submit">Submit</button>
</div>
</EditForm>
@code {
[SupplyParameterFromForm]
private Ship? Model { get; set; }
protected override void OnInitialized() => Model ??= new();
private void Submit() =>
Logger.LogInformation("Id = {Id} Desc = {Description} Length = {Length}",
Model?.Id, Model?.Details?.Description, Model?.Details?.Length);
}
使用靜態 SSR 初始化表格資料
當元件採用靜態 SSR 時,OnInitialized{Async}
生命週期方法和OnParametersSet{Async}
生命週期方法會在元件初始呈現和每次表單 POST 到伺服器時啟動。 若要初始化表單模型值,在 OnParametersSet{Async}
中指定新的模型值之前,先確認模型是否已經有資料,就像下面的範例所展示的一樣。
StarshipInit.razor
:
@page "/starship-init"
@inject ILogger<StarshipInit> Logger
<EditForm Model="Model" OnValidSubmit="Submit" FormName="StarshipInit">
<div>
<label>
Identifier:
<InputText @bind-Value="Model!.Id" />
</label>
</div>
<div>
<button type="submit">Submit</button>
</div>
</EditForm>
@code {
[SupplyParameterFromForm]
private Starship? Model { get; set; }
protected override void OnInitialized() => Model ??= new();
protected override void OnParametersSet()
{
if (Model!.Id == default)
{
LoadData();
}
}
private void LoadData()
{
Model!.Id = "Set by LoadData";
}
private void Submit()
{
Logger.LogInformation("Id = {Id}", Model?.Id);
}
public class Starship
{
public string? Id { get; set; }
}
}
進階表單對應錯誤案例
架構會具現化並填入表單的 FormMappingContext,這是與指定表單對應作業相關聯的內容。 每個對應範圍 (由 FormMappingScope 元件定義) 都會具現化 FormMappingContext。 每次 [SupplyParameterFromForm]
向內容要求值時,架構都會以嘗試的值和任何對應錯誤填入 FormMappingContext。
開發人員預期不會直接與 FormMappingContext 互動,因為它主要是 InputBase<TValue>、EditContext 和其他內部實作的資料來源,以將對應錯誤顯示為驗證錯誤。 在進階自訂案例中,開發人員可以以 [CascadingParameter]
的形式直接存取 FormMappingContext,以便撰寫會取用嘗試的值和對應錯誤的自訂程式碼。
自訂輸入元件
對於自訂輸入處理案例,下列子區段示範自訂輸入元件:
以
InputBase<T>
為基礎的輸入元件:元件繼承自 InputBase<TValue>,其提供繫結、回呼和驗證的基礎實作。 繼承自 InputBase<TValue> 的元件必須用於 Blazor 表單 (EditForm)。具有完整開發人員控制項的輸入元件:元件完全掌控輸入處理。 元件的程式碼必須管理繫結、回呼和驗證。 元件可以在 Blazor 表單內部或外部使用。
建議您從 InputBase<TValue> 衍生自訂輸入元件,除非特定需求阻止執行此動作。 ASP.NET Core 小組會主動維護此 InputBase<TValue> 類別,確保其隨時掌握最新的 Blazor 功能和架構變更。
以 InputBase<T>
為基礎的輸入元件
下列範例元件:
- 繼承自 InputBase<TValue>。 繼承自 InputBase<TValue> 的元件必須用於 Blazor 表單 (EditForm)。
- 從核取方塊中取得布林值輸入。
- 根據核取方塊的狀態設定其容器
<div>
的背景色彩,當AfterChange
方法在繫結之後 (@bind:after
) 執行時會發生這種情況。 - 需要覆寫基底類別的
TryParseValueFromString
方法,但不會處理字串輸入資料,因為核取方塊不提供字串資料。 其他輸入元件類型的TryParseValueFromString
範例實作,其會處理 ASP.NET Core 參考來源中提供的字串輸入。
注意
.NET 參考來源的文件連結通常會載入存放庫的預設分支,這表示下一版 .NET 的目前開發。 若要選取特定版本的標籤,請使用 [切換分支或標籤] 下拉式清單。 如需詳細資訊,請參閱如何選取 ASP.NET Core 原始程式碼 (dotnet/AspNetCore.Docs #26205) 的版本標籤。
EngineeringApprovalInputDerived.razor
:
@using System.Diagnostics.CodeAnalysis
@inherits InputBase<bool>
<div class="@divCssClass">
<label>
Engineering Approval:
<input @bind="CurrentValue" @bind:after="AfterChange" class="@CssClass"
type="checkbox" />
</label>
</div>
@code {
private string? divCssClass;
private void AfterChange()
{
divCssClass = CurrentValue ? "bg-success text-white" : null;
}
protected override bool TryParseValueFromString(
string? value, out bool result,
[NotNullWhen(false)] out string? validationErrorMessage)
=> throw new NotSupportedException(
"This component does not parse string inputs. " +
$"Bind to the '{nameof(CurrentValue)}' property, " +
$"not '{nameof(CurrentValueAsString)}'.");
}
若要在星際飛船範例表單 (Starship3.razor
/Starship.cs
) 中使用上述元件,請使用繫結至模型之 IsValidatedDesign
屬性的 EngineeringApprovalInputDerived
元件執行個體,取代工程核准欄位的 <div>
區塊:
- <div>
- <label>
- Engineering Approval:
- <InputCheckbox @bind-Value="Model!.IsValidatedDesign" />
- </label>
- </div>
+ <EngineeringApprovalInputDerived @bind-Value="Model!.IsValidatedDesign" />
具有完整開發人員控制項的輸入元件
下列範例元件:
- 不會繼承自 InputBase<TValue>。 元件完全掌控輸入處理,包括繫結、回呼和驗證。 元件可以在 Blazor 表單 (EditForm) 內部或外部使用。
- 從核取方塊中取得布林值輸入。
- 如果已勾選核取方塊,請變更背景色彩。
元件中的程式碼包括:
Value
屬性搭配使用雙向繫結,以取得或設定輸入的值。ValueChanged
是更新繫結值的回呼。用於 Blazor 表單中時:
- EditContext 是串聯值。
fieldCssClass
根據 EditContext 驗證的結果設定欄位的樣式。ValueExpression
是由識別繫結值的架構所指派的運算式 (Expression<Func<T>>
)。- FieldIdentifier 能唯一識別可編輯的單一欄位,該欄位通常對應至模型屬性。 欄位識別碼的建立方式為,使用識別繫結值 (
ValueExpression
) 的運算式。
在
OnChange
事件處理常式中:- 核取方塊輸入的值是從 InputFileChangeEventArgs 中取得。
- 已設定容器
<div>
元素的背景色彩和文字色彩。 - EventCallback.InvokeAsync 會叫用與繫結相關聯的委派,並將事件通知分派給已變更值的取用者。
- 如果元件用於 EditForm (
EditContext
屬性不是null
),則會呼叫 EditContext.NotifyFieldChanged 以觸發驗證。
EngineeringApprovalInputStandalone.razor
:
@using System.Globalization
@using System.Linq.Expressions
<div class="@divCssClass">
<label>
Engineering Approval:
<input class="@fieldCssClass" @onchange="OnChange" type="checkbox"
value="@Value" />
</label>
</div>
@code {
private string? divCssClass;
private FieldIdentifier fieldIdentifier;
private string? fieldCssClass => EditContext?.FieldCssClass(fieldIdentifier);
[CascadingParameter]
private EditContext? EditContext { get; set; }
[Parameter]
public bool? Value { get; set; }
[Parameter]
public EventCallback<bool> ValueChanged { get; set; }
[Parameter]
public Expression<Func<bool>>? ValueExpression { get; set; }
protected override void OnInitialized()
{
fieldIdentifier = FieldIdentifier.Create(ValueExpression!);
}
private async Task OnChange(ChangeEventArgs args)
{
BindConverter.TryConvertToBool(args.Value, CultureInfo.CurrentCulture,
out var value);
divCssClass = value ? "bg-success text-white" : null;
await ValueChanged.InvokeAsync(value);
EditContext?.NotifyFieldChanged(fieldIdentifier);
}
}
若要在星際飛船範例表單 (Starship3.razor
/Starship.cs
) 中使用上述元件,請使用繫結至模型之 IsValidatedDesign
屬性的 EngineeringApprovalInputStandalone
元件執行個體,取代工程核准欄位的 <div>
區塊:
- <div>
- <label>
- Engineering Approval:
- <InputCheckbox @bind-Value="Model!.IsValidatedDesign" />
- </label>
- </div>
+ <EngineeringApprovalInputStandalone @bind-Value="Model!.IsValidatedDesign" />
EngineeringApprovalInputStandalone
元件也可以在 EditForm 外部運作:
<EngineeringApprovalInputStandalone @bind-Value="ValidDesign" />
<div>
<b>ValidDesign:</b> @ValidDesign
</div>
@code {
private bool ValidDesign { get; set; }
}
選項按鈕
本節中的範例是以本文範例表單小節的 Starfleet Starship Database
表單 (Starship3
元件) 為基礎。
將下列 enum
型別新增至應用程式。 建立新的檔案來保存它們,或將它們新增至 Starship.cs
檔案。
public class ComponentEnums
{
public enum Manufacturer { SpaceX, NASA, ULA, VirginGalactic, Unknown }
public enum Color { ImperialRed, SpacecruiserGreen, StarshipBlue, VoyagerOrange }
public enum Engine { Ion, Plasma, Fusion, Warp }
}
讓 ComponentEnums
類別可供存取:
Starship.cs
中的Starship
模型 (例如,using static ComponentEnums;
)。Starfleet Starship Database
表單 (Starship3.razor
) (例如,@using static ComponentEnums
)。
使用 InputRadio<TValue> 元件搭配 InputRadioGroup<TValue> 元件來建立選項按鈕群組。 在下列範例中,屬性會新增至輸入元件一文中的範例表單小節所說明的 Starship
模型:
[Required]
[Range(typeof(Manufacturer), nameof(Manufacturer.SpaceX),
nameof(Manufacturer.VirginGalactic), ErrorMessage = "Pick a manufacturer.")]
public Manufacturer Manufacturer { get; set; } = Manufacturer.Unknown;
[Required, EnumDataType(typeof(Color))]
public Color? Color { get; set; } = null;
[Required, EnumDataType(typeof(Engine))]
public Engine? Engine { get; set; } = null;
更新輸入元件一文中範例表單小節的 Starfleet Starship Database
表單 (Starship3
元件)。 新增要產生的元件:
- 飛船製造商的選項按鈕群組。
- 引擎和飛船色彩的巢狀選項按鈕群組。
注意
巢狀選項按鈕群組不常用於表單,因為它們可能會導致表單控制項的配置錯亂,進而可能混淆使用者。 不過,在某些情況下它們在 UI 設計中有意義,例如會配對兩個使用者輸入、飛船引擎和飛船色彩建議的下列範例。 表單驗證需要一個引擎和一種色彩。 表單的配置會使用巢狀 InputRadioGroup<TValue> 來配對引擎和色彩建議。 不過,使用者可以結合任何引擎與任何色彩來提交表單。
注意
針對下列範例,務必將 ComponentEnums
類別提供給元件:
@using static ComponentEnums
<fieldset>
<legend>Manufacturer</legend>
<InputRadioGroup @bind-Value="Model!.Manufacturer">
@foreach (var manufacturer in Enum.GetValues<Manufacturer>())
{
<div>
<label>
<InputRadio Value="manufacturer" />
@manufacturer
</label>
</div>
}
</InputRadioGroup>
</fieldset>
<fieldset>
<legend>Engine and Color</legend>
<p>
Engine and color pairs are recommended, but any
combination of engine and color is allowed.
</p>
<InputRadioGroup Name="engine" @bind-Value="Model!.Engine">
<InputRadioGroup Name="color" @bind-Value="Model!.Color">
<div style="margin-bottom:5px">
<div>
<label>
<InputRadio Name="engine" Value="Engine.Ion" />
Ion
</label>
</div>
<div>
<label>
<InputRadio Name="color" Value="Color.ImperialRed" />
Imperial Red
</label>
</div>
</div>
<div style="margin-bottom:5px">
<div>
<label>
<InputRadio Name="engine" Value="Engine.Plasma" />
Plasma
</label>
</div>
<div>
<label>
<InputRadio Name="color" Value="Color.SpacecruiserGreen" />
Spacecruiser Green
</label>
</div>
</div>
<div style="margin-bottom:5px">
<div>
<label>
<InputRadio Name="engine" Value="Engine.Fusion" />
Fusion
</label>
</div>
<div>
<label>
<InputRadio Name="color" Value="Color.StarshipBlue" />
Starship Blue
</label>
</div>
</div>
<div style="margin-bottom:5px">
<div>
<label>
<InputRadio Name="engine" Value="Engine.Warp" />
Warp
</label>
</div>
<div>
<label>
<InputRadio Name="color" Value="Color.VoyagerOrange" />
Voyager Orange
</label>
</div>
</div>
</InputRadioGroup>
</InputRadioGroup>
</fieldset>
注意
如果省略 Name
,InputRadio<TValue> 元件會依其最新的上階分組。
如果您在輸入元件一文的範例表單小節的 Starship3
元件中實作上述 Razor 標記,請更新 Submit
方法的記錄:
Logger.LogInformation("Id = {Id} Description = {Description} " +
"Classification = {Classification} MaximumAccommodation = " +
"{MaximumAccommodation} IsValidatedDesign = " +
"{IsValidatedDesign} ProductionDate = {ProductionDate} " +
"Manufacturer = {Manufacturer}, Engine = {Engine}, " +
"Color = {Color}",
Model?.Id, Model?.Description, Model?.Classification,
Model?.MaximumAccommodation, Model?.IsValidatedDesign,
Model?.ProductionDate, Model?.Manufacturer, Model?.Engine,
Model?.Color);
在表單中使用選項按鈕時,資料繫結的處理方式與其他元素不同,因為會將選項按鈕評估為群組。 每個選項按鈕的值都是固定的,但選項按鈕群組的值是所選選項按鈕的值。 下列範例顯示如何:
- 處理選項按鈕群組的資料繫結。
- 支援使用自訂 InputRadio<TValue> 進行驗證。
InputRadio.razor
:
@using System.Globalization
@inherits InputBase<TValue>
@typeparam TValue
<input @attributes="AdditionalAttributes" type="radio" value="@SelectedValue"
checked="@(SelectedValue.Equals(Value))" @onchange="OnChange" />
@code {
[Parameter]
public TValue SelectedValue { get; set; }
private void OnChange(ChangeEventArgs args)
{
CurrentValueAsString = args.Value.ToString();
}
protected override bool TryParseValueFromString(string value,
out TValue result, out string errorMessage)
{
var success = BindConverter.TryConvertTo<TValue>(
value, CultureInfo.CurrentCulture, out var parsedValue);
if (success)
{
result = parsedValue;
errorMessage = null;
return true;
}
else
{
result = default;
errorMessage = "The field isn't valid.";
return false;
}
}
}
如需泛型型別參數 (@typeparam
) 的詳細資訊,請參閱下列文章:
使用下列範例模型。
StarshipModel.cs
:
using System.ComponentModel.DataAnnotations;
namespace BlazorServer80
{
public class Model
{
[Range(1, 5)]
public int Rating { get; set; }
}
}
下列 RadioButtonExample
元件會使用上述 InputRadio
元件,以從使用者取得及驗證評等:
RadioButtonExample.razor
:
@page "/radio-button-example"
@using System.ComponentModel.DataAnnotations
@using Microsoft.Extensions.Logging
@inject ILogger<RadioButtonExample> Logger
<h1>Radio Button Example</h1>
<EditForm Model="Model" OnValidSubmit="HandleValidSubmit">
<DataAnnotationsValidator />
<ValidationSummary />
@for (int i = 1; i <= 5; i++)
{
<div>
<label>
<InputRadio name="rate" SelectedValue="i"
@bind-Value="Model.Rating" />
@i
</label>
</div>
}
<div>
<button type="submit">Submit</button>
</div>
</EditForm>
<div>@Model.Rating</div>
@code {
public StarshipModel Model { get; set; }
protected override void OnInitialized() => Model ??= new();
private void HandleValidSubmit()
{
Logger.LogInformation("HandleValidSubmit called");
}
}