powiązanie formularzy ASP.NET Core Blazor
Uwaga
Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z bieżącą wersją, zapoznaj się z wersją tego artykułu platformy .NET 8.
Ostrzeżenie
Ta wersja ASP.NET Core nie jest już obsługiwana. Aby uzyskać więcej informacji, zobacz .NET i .NET Core Support Policy (Zasady obsługi platformy .NET Core). Aby zapoznać się z bieżącą wersją, zapoznaj się z wersją tego artykułu platformy .NET 8.
Ważne
Te informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany, zanim zostanie wydany komercyjnie. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.
Aby zapoznać się z bieżącą wersją, zapoznaj się z wersją tego artykułu platformy .NET 8.
W tym artykule wyjaśniono, jak używać powiązania w Blazor formularzach.
EditForm
/EditContext
model
Obiekt EditForm tworzy EditContext obiekt oparty na przypisanym obiekcie jako wartość kaskadową dla innych składników w formularzu. Śledzi EditContext metadane dotyczące procesu edycji, w tym pola formularza, które zostały zmodyfikowane, oraz bieżące komunikaty sprawdzania poprawności. Przypisanie do obiektu EditForm.Model lub EditForm.EditContext może powiązać formularz z danymi.
Powiązanie modelu
Przypisanie do :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();
}
Uwaga
Większość przykładów modelu formularzy tego artykułu wiąże formularze z właściwościami języka C#, ale obsługiwane jest również powiązanie pól języka C#.
Powiązanie kontekstu
Przypisanie do :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);
}
}
Przypisz element EditContext lub do Model elementu EditForm. Jeśli oba te elementy zostaną przypisane, zostanie zgłoszony błąd środowiska uruchomieniowego.
Obsługiwane typy
Powiązanie obsługuje:
- Typy pierwotne
- Kolekcje
- Typy złożone
- Typy rekursywne
- Typy z konstruktorami
- Wyliczenia
Można również użyć [DataMember]
atrybutów i [IgnoreDataMember]
, aby dostosować powiązanie modelu. Użyj tych atrybutów, aby zmienić nazwy właściwości, zignorować właściwości i oznaczyć właściwości zgodnie z potrzebami.
Dodatkowe opcje powiązania
Dodatkowe opcje powiązania modelu są dostępne podczas RazorComponentsServiceOptions wywoływania elementu AddRazorComponents:
- MaxFormMappingCollectionSize: Maksymalna liczba elementów dozwolonych w kolekcji formularzy.
- MaxFormMappingRecursionDepth: Maksymalna głębokość dozwolona podczas cyklicznego mapowania danych formularza.
- MaxFormMappingErrorCount: Maksymalna liczba błędów dozwolonych podczas mapowania danych formularza.
- MaxFormMappingKeySize: maksymalny rozmiar buforu używanego do odczytywania kluczy danych formularza.
Poniżej przedstawiono wartości domyślne przypisane przez strukturę:
builder.Services.AddRazorComponents(options =>
{
options.FormMappingUseCurrentCulture = true;
options.MaxFormMappingCollectionSize = 1024;
options.MaxFormMappingErrorCount = 200;
options.MaxFormMappingKeySize = 1024 * 2;
options.MaxFormMappingRecursionDepth = 64;
}).AddInteractiveServerComponents();
Nazwy formularzy
Użyj parametru , FormName aby przypisać nazwę formularza. Nazwy formularzy muszą być unikatowe w celu powiązania danych modelu. Następujący formularz nosi nazwę RomulanAle
:
<EditForm ... FormName="RomulanAle" ...>
...
</EditForm>
Podawanie nazwy formularza:
- Jest wymagany dla wszystkich formularzy przesyłanych przez statycznie renderowane składniki po stronie serwera.
- Nie jest wymagane w przypadku formularzy przesyłanych przez składniki renderowane interaktywnie, w tym formularze w Blazor WebAssembly aplikacjach i składnikach z trybem renderowania interakcyjnego. Zalecamy jednak podanie unikatowej nazwy formularza dla każdego formularza, aby zapobiec wysyłaniu błędów formularza w czasie wykonywania, jeśli kiedykolwiek przerywana jest interakcyjność dla formularza.
Nazwa formularza jest sprawdzana tylko wtedy, gdy formularz jest publikowany w punkcie końcowym jako tradycyjne żądanie HTTP POST ze statycznie renderowanego składnika po stronie serwera. Struktura nie zgłasza wyjątku w momencie renderowania formularza, ale tylko w momencie nadejścia żądania HTTP POST i nie określa nazwy formularza.
Istnieje zakres formularza bez nazwy (pusty ciąg) powyżej składnika głównego aplikacji, który wystarczy, gdy w aplikacji nie ma kolizji nazw formularzy. Jeśli możliwe są kolizje nazw formularzy, na przykład w przypadku dołączania formularza z biblioteki i nie masz kontroli nad nazwą formularza używaną przez dewelopera biblioteki, podaj zakres nazw formularzy ze FormMappingScope składnikiem w Blazor Web Appgłównym projekcie biblioteki.
W poniższym przykładzie HelloFormFromLibrary
składnik ma postać o nazwie Hello
i znajduje się w bibliotece.
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;
}
Poniższy NamedFormsWithScope
składnik używa składnika biblioteki HelloFormFromLibrary
, a także ma formularz o nazwie Hello
. FormMappingScope Nazwa zakresu składnika dotyczy ParentContext
dowolnych formularzy dostarczonych przez HelloFormFromLibrary
składnik. Mimo że obie formularze w tym przykładzie mają nazwę formularza (Hello
), nazwy formularzy nie zderzają się, a zdarzenia są kierowane do poprawnego formularza dla zdarzeń POST formularza.
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;
}
Podaj parametr z formularza ([SupplyParameterFromForm]
)
Atrybut [SupplyParameterFromForm]
wskazuje, że wartość skojarzonej właściwości powinna być dostarczana z danych formularza dla formularza. Dane w żądaniu, które pasują do nazwy właściwości, są powiązane z właściwością. Dane wejściowe oparte na InputBase<TValue>
generowaniu nazw wartości formularza, które są zgodne z nazwami Blazor używanymi do powiązania modelu. W przeciwieństwie do właściwości parametru składnika ([Parameter]
), właściwości z adnotacjami [SupplyParameterFromForm]
nie są wymagane do oznaczenia public
.
Do atrybutu [SupplyParameterFromForm]
można określić następujące parametry powiązania formularza:
- Name: Pobiera lub ustawia nazwę parametru. Nazwa służy do określania prefiksu używanego do dopasowania danych formularza i decydowania, czy wartość musi być powiązana.
- FormName: Pobiera lub ustawia nazwę programu obsługi. Nazwa jest używana do dopasowania parametru do formularza według nazwy formularza, aby zdecydować, czy wartość musi być powiązana.
Poniższy przykład niezależnie wiąże dwa formularze z modelami według nazwy formularza.
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; }
}
}
Zagnieżdżanie i wiązanie formularzy
Poniższe wskazówki pokazują, jak zagnieżdżać i wiązać formularze podrzędne.
Następująca klasa szczegółów wysyłki (ShipDetails
) zawiera opis i długość podformularza.
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; }
}
Poniższa Ship
klasa nazywa identyfikator (Id
) i zawiera szczegóły wysyłki.
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();
}
}
Poniższy podformularz jest używany do edytowania ShipDetails
wartości typu. Jest to implementowane przez dziedziczenie Editor<T> w górnej części składnika. Editor<T>gwarantuje, że składnik podrzędny generuje poprawne nazwy pól formularza na podstawie modelu (T
), gdzie T
w poniższym przykładzie jest .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>
Formularz główny jest powiązany z klasą Ship
. Składnik służy do edytowania StarshipSubform
szczegółów wysyłki powiązanej jako 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);
}
Inicjowanie danych formularza za pomocą statycznego przewodnika SSR
Gdy składnik przyjmuje statyczny SSR, metoda cyklu życia i OnParametersSet{Async}
metoda cyklu życia są uruchamiane, OnInitialized{Async}
gdy składnik jest początkowo renderowany i na każdym formularzu POST na serwerze. Aby zainicjować wartości modelu formularza, upewnij się, że model ma już dane przed przypisanie nowych wartości modelu w programie OnParametersSet{Async}
, jak pokazano w poniższym przykładzie.
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; }
}
}
Zaawansowane scenariusze błędów mapowania formularzy
Struktura tworzy wystąpienie i wypełnia FormMappingContext formularz, który jest kontekstem skojarzonym z operacją mapowania danego formularza. Każdy zakres mapowania (zdefiniowany przez FormMappingScope składnik) tworzy wystąpienie FormMappingContext. Za każdym razem, gdy [SupplyParameterFromForm]
element kontekst o wartość, struktura wypełnia FormMappingContext element wartością próbną i wszelkimi błędami mapowania.
Deweloperzy nie powinni korzystać bezpośrednio, FormMappingContext ponieważ jest to głównie źródło danych dla InputBase<TValue>programu , EditContexti innych wewnętrznych implementacji w celu wyświetlania błędów mapowania jako błędów walidacji. W zaawansowanych scenariuszach niestandardowych deweloperzy mogą uzyskiwać dostęp FormMappingContext bezpośrednio jako element [CascadingParameter]
do pisania kodu niestandardowego, który korzysta z próbowanych wartości i błędów mapowania.
Niestandardowe składniki wejściowe
W przypadku niestandardowych scenariuszy przetwarzania danych wejściowych w poniższych podsekcjach przedstawiono niestandardowe składniki wejściowe:
Składnik wejściowy oparty na :
InputBase<T>
składnik dziedziczy z InputBase<TValue>elementu , który zapewnia podstawową implementację powiązań, wywołań zwrotnych i walidacji. Składniki dziedziczone z InputBase<TValue> programu muszą być używane w formularzu Blazor (EditForm).Składnik wejściowy z pełną kontrolą dewelopera: składnik przejmuje pełną kontrolę nad przetwarzaniem wejściowym. Kod składnika musi zarządzać powiązaniami, wywołaniami zwrotnymi i walidacją. Składnik może być używany wewnątrz formularza lub poza nim Blazor .
Zalecamy tworzenie niestandardowych składników wejściowych, InputBase<TValue> chyba że określone wymagania uniemożliwiają wykonanie tych czynności. Klasa InputBase<TValue> jest aktywnie utrzymywana przez zespół ASP.NET Core, zapewniając, że jest aktualna dzięki najnowszym Blazor funkcjom i zmianom struktury.
Składnik wejściowy na podstawie InputBase<T>
Poniższy przykładowy składnik:
- Dziedziczy z obiektu InputBase<TValue>. Składniki dziedziczone z InputBase<TValue> programu muszą być używane w formularzu Blazor (EditForm).
- Pobiera dane wejściowe logiczne z pola wyboru.
- Ustawia kolor tła kontenera
<div>
na podstawie stanu pola wyboru, który występuje, gdyAfterChange
metoda jest wykonywana po powiązaniu (@bind:after
). - Wymagane jest zastąpienie metody klasy
TryParseValueFromString
bazowej, ale nie przetwarza danych wejściowych ciągu, ponieważ pole wyboru nie dostarcza danych ciągów. Przykładowe implementacjeTryParseValueFromString
dla innych typów składników wejściowych, które przetwarzają dane wejściowe ciągu, są dostępne w źródle referencyjnym ASP.NET Core.
Uwaga
Linki dokumentacji do źródła referencyjnego platformy .NET zwykle ładują domyślną gałąź repozytorium, która odzwierciedla bieżące programowanie dla następnej wersji platformy .NET. Aby wybrać tag dla określonej wersji, użyj listy rozwijanej Przełącz gałęzie lub tagi. Aby uzyskać więcej informacji, zobacz Jak wybrać tag wersji kodu źródłowego platformy 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)}'.");
}
Aby użyć poprzedniego składnika w przykładowym formularzu starship (Starship3.razor
/Starship.cs
), zastąp <div>
blok pola zatwierdzenia inżynieryjnego wystąpieniem składnika powiązanym EngineeringApprovalInputDerived
z właściwością modelu IsValidatedDesign
:
- <div>
- <label>
- Engineering Approval:
- <InputCheckbox @bind-Value="Model!.IsValidatedDesign" />
- </label>
- </div>
+ <EngineeringApprovalInputDerived @bind-Value="Model!.IsValidatedDesign" />
Składnik wejściowy z pełną kontrolą dewelopera
Poniższy przykładowy składnik:
- Nie dziedziczy z elementu InputBase<TValue>. Składnik przejmuje pełną kontrolę nad przetwarzaniem wejściowym, w tym powiązaniem, wywołaniami zwrotnymi i walidacją. Składnik może być używany wewnątrz lub na zewnątrz Blazor formularza (EditForm).
- Pobiera dane wejściowe logiczne z pola wyboru.
- Zmienia kolor tła, jeśli pole wyboru jest zaznaczone.
Kod w składniku obejmuje:
Właściwość
Value
jest używana z powiązaniem dwukierunkowym, aby uzyskać lub ustawić wartość danych wejściowych.ValueChanged
to wywołanie zwrotne, które aktualizuje powiązaną wartość.W przypadku użycia w formularzu Blazor :
- Jest EditContext to wartość kaskadowa.
fieldCssClass
style pola na podstawie wyniku weryfikacji EditContext .ValueExpression
jest wyrażeniem (Expression<Func<T>>
) przypisanym przez strukturę identyfikującą powiązaną wartość.- FieldIdentifier unikatowo identyfikuje jedno pole, które można edytować, zwykle odpowiadające właściwości modelu. Identyfikator pola jest tworzony za pomocą wyrażenia identyfikującego powiązaną wartość (
ValueExpression
).
W programie obsługi zdarzeń
OnChange
:- Wartość danych wejściowych pola wyboru jest uzyskiwana z InputFileChangeEventArgselementu .
- Ustawiono kolor tła i kolor tekstu elementu kontenera
<div>
. - EventCallback.InvokeAsync wywołuje delegata skojarzonego z powiązaniem i wysyła powiadomienie o zdarzeniu do odbiorców, że wartość została zmieniona.
- Jeśli składnik jest używany w elemencie EditForm (właściwość nie
null
jest ), EditContext.NotifyFieldChanged jest wywoływany w celu wyzwoleniaEditContext
walidacji.
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);
}
}
Aby użyć poprzedniego składnika w przykładowym formularzu starship (Starship3.razor
/Starship.cs
), zastąp <div>
blok pola zatwierdzenia inżynieryjnego wystąpieniem składnika powiązanym EngineeringApprovalInputStandalone
z właściwością modelu IsValidatedDesign
:
- <div>
- <label>
- Engineering Approval:
- <InputCheckbox @bind-Value="Model!.IsValidatedDesign" />
- </label>
- </div>
+ <EngineeringApprovalInputStandalone @bind-Value="Model!.IsValidatedDesign" />
Składnik EngineeringApprovalInputStandalone
działa również poza elementem EditForm:
<EngineeringApprovalInputStandalone @bind-Value="ValidDesign" />
<div>
<b>ValidDesign:</b> @ValidDesign
</div>
@code {
private bool ValidDesign { get; set; }
}
Przycisków
Przykład w tej sekcji jest oparty na formularzu Starfleet Starship Database
(Starship3
składnik) sekcji Przykładowy formularz tego artykułu.
Dodaj następujące enum
typy do aplikacji. Utwórz nowy plik do przechowywania lub dodaj go do Starship.cs
pliku.
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 }
}
Udostępnij klasę ComponentEnums
:
Starship
model inStarship.cs
(na przykładusing static ComponentEnums;
).Starfleet Starship Database
form () (Starship3.razor
na przykład@using static ComponentEnums
).
Użyj InputRadio<TValue> składników ze składnikiem InputRadioGroup<TValue> , aby utworzyć grupę przycisków radiowych. W poniższym przykładzie właściwości są dodawane do Starship
modelu opisanego w sekcji Przykładowy formularz artykułu Składniki wejściowe:
[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
Zaktualizuj formularz (Starship3
składnik) sekcji Przykładowy formularz artykułu Składniki wejściowe. Dodaj składniki do utworzenia:
- Grupa przycisków radiowych dla producenta statku.
- Zagnieżdżona grupa przycisków radiowych dla silnika i koloru wysyłki.
Uwaga
Zagnieżdżone grupy przycisków radiowych nie są często używane w formularzach, ponieważ mogą one spowodować dezorganizowany układ kontrolek formularzy, które mogą mylić użytkowników. Istnieją jednak przypadki, gdy mają sens w projekcie interfejsu użytkownika, na przykład w poniższym przykładzie, które łączą zalecenia dotyczące dwóch danych wejściowych użytkownika, silnika wysyłkowego i koloru wysyłki. Jeden aparat i jeden kolor są wymagane przez walidację formularza. Układ formularza używa zagnieżdżonych InputRadioGroup<TValue>elementów do parowania aparatu i zaleceń dotyczących kolorów. Jednak użytkownik może połączyć dowolny aparat z dowolnym kolorem, aby przesłać formularz.
Uwaga
Upewnij się, że ComponentEnums
klasa jest dostępna dla składnika w następującym przykładzie:
@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>
Uwaga
Jeśli Name
pominięto, InputRadio<TValue> składniki są pogrupowane według ich najnowszego modułu ancestor.
Jeśli zaimplementowano powyższy Razor znacznik w Starship3
składniku sekcji Przykładowy formularz artykułu Składniki wejściowe, zaktualizuj rejestrowanie dla Submit
metody :
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);
Podczas pracy z przyciskami radiowymi w formularzu powiązanie danych jest obsługiwane inaczej niż inne elementy, ponieważ przyciski radiowe są oceniane jako grupa. Wartość każdego przycisku radiowego jest stała, ale wartość grupy przycisków radiowych jest wartością wybranego przycisku radiowego. W poniższym przykładzie pokazano, jak:
- Obsługa powiązania danych dla grupy przycisków radiowych.
- Obsługa walidacji przy użyciu składnika niestandardowego 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;
}
}
}
Aby uzyskać więcej informacji na temat ogólnych parametrów typu (@typeparam
), zobacz następujące artykuły:
- Dokumentacja składni aparatu Razor dla platformy ASP.NET Core
- składniki ASP.NET Core Razor
- Składniki z szablonami na platformie ASP.NET Core Blazor
Użyj następującego przykładowego modelu.
StarshipModel.cs
:
using System.ComponentModel.DataAnnotations;
namespace BlazorServer80
{
public class Model
{
[Range(1, 5)]
public int Rating { get; set; }
}
}
RadioButtonExample
Poniższy składnik używa poprzedniego InputRadio
składnika do uzyskania i zweryfikowania oceny od użytkownika:
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");
}
}