ASP.NET Core Blazor formulärbindning
Not
Det här är inte den senaste versionen av den här artikeln. Den aktuella versionen finns i den .NET 9-versionen av den här artikeln.
Varning
Den här versionen av ASP.NET Core stöds inte längre. Mer information finns i .NET och .NET Core Support Policy. Den aktuella versionen av den här artikeln finns i .NET 9-versionen .
Viktig
Den här informationen gäller en förhandsversionsprodukt som kan ändras avsevärt innan den släpps kommersiellt. Microsoft lämnar inga garantier, uttryckliga eller underförstådda, med avseende på den information som tillhandahålls här.
Den aktuella versionen finns i den .NET 9-versionen av den här artikeln.
Den här artikeln beskriver hur du använder bindning i Blazor formulär.
EditForm
/
EditContext
modell
En EditForm skapar en EditContext baserat på det tilldelade objektet som ett kaskadvärde för andra komponenter i formuläret. EditContext spårar metadata om redigeringsprocessen, inklusive vilka formulärfält som har ändrats och de aktuella valideringsmeddelandena. Tilldelning till antingen en EditForm.Model eller en EditForm.EditContext kan binda ett formulär till data.
Modellbindning
Tilldelning till 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();
}
Not
De flesta av den här artikelns formulärmodellexempel binder formulär till C# egenskaper, men C#-fältbindning stöds också.
Kontextbindning
Tilldelning till 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);
}
}
Tilldela antingen en EditContexteller en Model till en EditForm. Om båda tilldelas genereras ett körningsfel.
Typer som stöds
Bindningsstöd:
- Primitiva typer
- Samlingar
- Komplexa typer
- Rekursiva typer
- Typer med konstruktorer
- Uppräkningar
Du kan också använda attributen [DataMember]
och [IgnoreDataMember]
för att anpassa modellbindningen. Använd dessa attribut för att byta namn på egenskaper, ignorera egenskaper och markera egenskaper efter behov.
Ytterligare bindningsalternativ
Ytterligare alternativ för modellbindning är tillgängliga från RazorComponentsServiceOptions när du anropar AddRazorComponents:
- MaxFormMappingCollectionSize: Maximalt antal element som tillåts i en formulärsamling.
- MaxFormMappingRecursionDepth: Maximalt djup tillåts vid rekursiv mappning av formulärdata.
- MaxFormMappingErrorCount: Maximalt antal fel som tillåts vid mappning av formulärdata.
- MaxFormMappingKeySize: Maximal storlek på bufferten som används för att läsa formulärdatanycklar.
Följande visar standardvärdena som tilldelats av ramverket:
builder.Services.AddRazorComponents(options =>
{
options.FormMappingUseCurrentCulture = true;
options.MaxFormMappingCollectionSize = 1024;
options.MaxFormMappingErrorCount = 200;
options.MaxFormMappingKeySize = 1024 * 2;
options.MaxFormMappingRecursionDepth = 64;
}).AddInteractiveServerComponents();
Formulärnamn
Använd parametern FormName för att tilldela ett formulärnamn. Formulärnamn måste vara unika för att binda modelldata. Följande formulär heter RomulanAle
:
<EditForm ... FormName="RomulanAle" ...>
...
</EditForm>
Anger ett formulärnamn:
- Krävs för alla formulär som skickas av statiskt renderade komponenter på serversidan.
- Krävs inte för formulär som skickas av interaktivt renderade komponenter, som innehåller formulär i Blazor WebAssembly appar och komponenter med ett interaktivt återgivningsläge. Vi rekommenderar dock att du anger ett unikt formulärnamn för varje formulär för att förhindra runtime-formulärpubliceringsfel om interaktivitet någonsin tas bort för ett formulär.
Formulärnamnet kontrolleras endast när formuläret publiceras till en slutpunkt som en traditionell HTTP POST-begäran från en statiskt renderad komponent på serversidan. Ramverket utlöser inte ett undantag vid tidpunkten för återgivning av ett formulär, men bara vid den tidpunkt då en HTTP POST anländer och inte anger ett formulärnamn.
Det finns ett namnlöst (tom sträng) formuläromfång ovanför appens rotkomponent, vilket räcker när det inte finns några kollisioner med formulärnamn i appen. Om kollisioner med formulärnamn är möjliga, till exempel när du inkluderar ett formulär från ett bibliotek och du inte har någon kontroll över det formulärnamn som används av bibliotekets utvecklare, anger du ett formulärnamnsomfång med FormMappingScope komponenten i Blazor Web Apphuvudprojekt.
I följande exempel har komponenten HelloFormFromLibrary
ett formulär med namnet Hello
och finns i ett bibliotek.
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;
}
Följande NamedFormsWithScope
komponent använder bibliotekets HelloFormFromLibrary
komponent och har även ett formulär med namnet Hello
.
FormMappingScope-komponentens omfångsnamn är ParentContext
för alla formulär som tillhandahålls av HelloFormFromLibrary
komponenten. Även om båda formulären i det här exemplet har formulärnamnet (Hello
), kolliderar inte formulärnamnen och händelserna dirigeras till rätt formulär för POST-formulärhändelser.
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;
}
Ange en parameter från formuläret ([SupplyParameterFromForm]
)
Attributet [SupplyParameterFromForm]
anger att värdet för den associerade egenskapen ska anges från formulärdata för formuläret. Data i begäran som matchar namnet på egenskapen är bundna till egenskapen. Indata baserade på InputBase<TValue>
genererar formulärvärdenamn som matchar namnen Blazor använder för modellbindning. Till skillnad från egenskaper för komponentparameter ([Parameter]
) behöver egenskaper som kommenterats med [SupplyParameterFromForm]
inte markeras public
.
Du kan ange följande formulärbindningsparametrar för attributet [SupplyParameterFromForm]
:
- Name: Hämtar eller anger namnet på parametern. Namnet används för att fastställa prefixet som ska användas för att matcha formulärdata och avgöra om värdet måste bindas eller inte.
- FormName: Hämtar eller anger namnet på hanteraren. Namnet används för att matcha parametern med formuläret efter formulärnamn för att avgöra om värdet måste bindas eller inte.
Följande exempel binder oberoende två formulär till sina modeller med hjälp av formulärnamnet.
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; }
}
}
Kapsla och binda formulär
Följande vägledning visar hur du kapslar och binder underordnade formulär.
Följande leveransinformationsklass (ShipDetails
) innehåller en beskrivning och längd för ett underformulär.
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; }
}
Följande Ship
klassificerar en identifierare (Id
) och innehåller leveransinformationen.
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();
}
}
Följande underformulär används för att redigera värden av den ShipDetails
typen. Detta implementeras genom att ärva Editor<T> överst i komponenten.
Editor<T> ser till att den underordnade komponenten genererar rätt formulärfältnamn baserat på modellen (T
), där T
i följande exempel är 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>
Huvudformuläret är bundet till klassen Ship
. Komponenten StarshipSubform
används för att redigera leveransinformation, bunden som 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);
}
Initiera formulärdata med statisk SSR
När en komponent använder statisk SSR OnParametersSet{Async}
, vilket visas i följande exempel.
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; }
}
}
Felscenarier för avancerad formulärmappning
Ramverket instansierar och fyller i FormMappingContext för ett formulär, vilket är kontexten som är associerad med ett visst formulärs mappningsåtgärd. Varje mappningsomfång (definierat av en FormMappingScope komponent) instansierar FormMappingContext. Varje gång en [SupplyParameterFromForm]
frågar kontexten om ett värde fyller ramverket FormMappingContext med det förfrågade värdet och eventuella mappningsfel.
Utvecklare förväntas inte interagera med FormMappingContext direkt, eftersom det främst är en datakälla för InputBase<TValue>, EditContextoch andra interna implementeringar för att visa mappningsfel som valideringsfel. I avancerade anpassade scenarier kan utvecklare komma åt FormMappingContext direkt som en [CascadingParameter]
för att skriva anpassad kod som hanterar de försökte värden och mappningsfelen.
Anpassade indatakomponenter
För scenarier för anpassad indatabearbetning visar följande underavsnitt anpassade indatakomponenter:
indatakomponent baserat på
InputBase<T>
: Komponenten ärver från InputBase<TValue>, som tillhandahåller en basimplementering för bindning, återanrop och validering. Komponenter som ärver från InputBase<TValue> måste användas i ett Blazor formulär (EditForm).indatakomponent med fullständig utvecklarkontroll: Komponenten tar fullständig kontroll över indatabearbetningen. Komponentens kod måste hantera bindning, återanrop och validering. Komponenten kan användas i eller utanför ett Blazor formulär.
Vi rekommenderar att du härleder dina anpassade indatakomponenter från InputBase<TValue> såvida inte specifika krav hindrar dig från att göra det. Klassen InputBase<TValue> underhålls aktivt av ASP.NET Core-teamet, vilket säkerställer att den förblir up-touppdaterad med de senaste funktionerna och ändringar i Blazor-ramverket.
Indatakomponent baserad på InputBase<T>
Följande exempelkomponent:
- Ärver från InputBase<TValue>. Komponenter som ärver från InputBase<TValue> måste användas i ett Blazor formulär (EditForm).
- Tar booleska indata från en kryssruta.
- Anger bakgrundsfärgen för containern
<div>
baserat på kryssrutans tillstånd, vilket inträffar när metodenAfterChange
körs efter bindningen (@bind:after
). - Krävs för att åsidosätta basklassens
TryParseValueFromString
-metod men bearbetar inte strängindata eftersom en kryssruta inte innehåller strängdata. Exempelimplementeringar avTryParseValueFromString
för andra typer av indatakomponenter som bearbetar strängindata finns i ASP.NET Core-referenskällan.
Not
Dokumentationslänkar till .NET-referenskällan läser vanligtvis in lagringsplatsens standardgren, vilket representerar den aktuella utvecklingen för nästa version av .NET. Om du vill välja en tagg för en specifik version använder du listrutan Växla grenar eller taggar. Mer information finns i Så här väljer du en versionstagg för ASP.NET Core-källkod (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)}'.");
}
Om du vill använda föregående komponent i exempelformuläret rymdskepp (Starship3.razor
/Starship.cs
)ersätter du <div>
-blocket för fältet för tekniskt godkännande med en EngineeringApprovalInputDerived
komponentinstans som är bunden till modellens egenskap IsValidatedDesign
:
- <div>
- <label>
- Engineering Approval:
- <InputCheckbox @bind-Value="Model!.IsValidatedDesign" />
- </label>
- </div>
+ <EngineeringApprovalInputDerived @bind-Value="Model!.IsValidatedDesign" />
Om komponenten som ärver från InputBase<TValue> någon gång renderas statiskt, bör du tilldela egenskapen InputBase<TValue>.NameAttributeValue till attributet name
för <input>
-elementen.
<input @bind="CurrentValue" @bind:after="AfterChange" class="@CssClass"
type="checkbox" name="@NameAttributeValue" />
Tidigare tilldelning är inte nödvändig om komponenten garanteras att alltid renderas interaktivt.
Indatakomponent med fullständig utvecklarkontroll
Följande exempelkomponent:
- Ärver inte från InputBase<TValue>. Komponenten tar fullständig kontroll över indatabearbetning, inklusive bindning, återanrop och validering. Komponenten kan användas i eller utanför ett Blazor formulär (EditForm).
- Tar booleska indata från en kryssruta.
- Ändrar bakgrundsfärgen om kryssrutan är markerad.
Koden i komponenten innehåller:
Egenskapen
Value
används med tvåvägsbindning för att hämta eller ange värdet för indata.ValueChanged
är återanropet som uppdaterar det bundna värdet.När det används i ett Blazor-format:
- EditContext är ett kaskaderande värde.
-
fieldCssClass
formatmallar fältet baserat på resultatet av EditContext validering. -
ValueExpression
är ett uttryck (Expression<Func<T>>
) som tilldelats av ramverket som identifierar det bundna värdet. -
FieldIdentifier identifierar unikt ett enda fält som kan redigeras, vilket vanligtvis motsvarar en modellegenskap. Fältidentifieraren skapas med uttrycket som identifierar det bundna värdet (
ValueExpression
).
I händelsehanteraren för
OnChange
:- Värdet för kryssrutans indata hämtas från InputFileChangeEventArgs.
- Bakgrundsfärgen och textfärgen för containern
<div>
element anges. - EventCallback.InvokeAsync anropar ombudet som är associerat med bindningen och skickar ett händelsemeddelande till konsumenter om att värdet har ändrats.
- Om komponenten används i en EditForm (egenskapen
EditContext
inte ärnull
) anropas EditContext.NotifyFieldChanged för att utlösa verifiering.
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);
}
}
Om du vill använda föregående komponent i exempelformuläret rymdskepp (Starship3.razor
/Starship.cs
)ersätter du <div>
-blocket för fältet för tekniskt godkännande med en EngineeringApprovalInputStandalone
komponentinstans som är bunden till modellens IsValidatedDesign
-egenskap:
- <div>
- <label>
- Engineering Approval:
- <InputCheckbox @bind-Value="Model!.IsValidatedDesign" />
- </label>
- </div>
+ <EngineeringApprovalInputStandalone @bind-Value="Model!.IsValidatedDesign" />
Komponenten EngineeringApprovalInputStandalone
fungerar också utanför en EditForm:
<EngineeringApprovalInputStandalone @bind-Value="ValidDesign" />
<div>
<b>ValidDesign:</b> @ValidDesign
</div>
@code {
private bool ValidDesign { get; set; }
}
Alternativknappar
Exemplet i denna sektion baseras på
Lägg till följande enum
typer i appen. Skapa en ny fil för att lagra dem eller lägg till dem i Starship.cs
-filen.
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 }
}
Gör klassen ComponentEnums
tillgänglig för:
-
Starship
-modellen iStarship.cs
(till exempelusing static ComponentEnums;
). -
Starfleet Starship Database
-formulär (Starship3.razor
) (till exempel@using static ComponentEnums
).
Använd komponenterna InputRadio<TValue> tillsammans med komponenten InputRadioGroup<TValue> för att skapa en alternativknappsgrupp. I följande exempel läggs egenskaper till i Starship
-modellen som beskrivs i avsnittet Exempelformulär i artikeln Indatakomponenter:
[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;
Uppdatera formuläret Starfleet Starship Database
(Starship3
komponent) i avsnittet Exempelformulär i artikeln Indatakomponenter. Lägg till komponenterna för att producera:
- En alternativknappsgrupp för fartygstillverkaren.
- En kapslad alternativknappgrupp för motor- och skeppsfärg.
Note
Inbäddade radioknappsgrupper används inte ofta i formulär eftersom de kan leda till en oorganiserad formulärlayout som kan förvirra användarna. Det finns dock fall då de är meningsfulla i UI-design, till exempel i följande exempel som parar rekommendationer för två användarindata, fartygsmotor och fartygsfärg. En motor och en färg krävs av formulärets validering. Formulärets layout använder kapslade InputRadioGroup<TValue>för att parkoppla motor- och färgrekommendationer. Användaren kan dock kombinera valfri motor med valfri färg för att skicka formuläret.
Note
Se till att göra ComponentEnums
-klassen tillgänglig för komponenten i följande exempel:
@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>
Obs
Om Name
utelämnas grupperas InputRadio<TValue> komponenter efter deras senaste förfader.
Om du implementerade föregående Razor-markering i Starship3
-komponenten i exempelformuläret avsnittet Indatakomponenter artikeln uppdaterar du loggningen för metoden 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);
När du arbetar med alternativknappar i ett formulär hanteras databindning på ett annat sätt än för andra element eftersom alternativknappar betraktas som en grupp. Värdet för varje alternativknapp är fast, men värdet för alternativknappsgruppen är värdet för den valda alternativknappen. I följande exempel visas hur du:
- Hantera databindning för en grupp radioknappar.
- Stöd för validering med hjälp av en anpassad InputRadio<TValue> komponent.
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;
}
}
}
Mer information om generiska typparametrar (@typeparam
) finns i följande artiklar:
- Razor syntaxreferens för ASP.NET Core
- ASP.NET Core Razor komponenter
- ASP.NET Core Blazor mallade komponenter
Använd följande exempelmodell.
StarshipModel.cs
:
using System.ComponentModel.DataAnnotations;
namespace BlazorServer80
{
public class Model
{
[Range(1, 5)]
public int Rating { get; set; }
}
}
Följande RadioButtonExample
komponent använder den föregående InputRadio
komponenten för att hämta och verifiera ett omdöme från användaren:
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");
}
}
ASP.NET Core