ASP.NET vazby základních Blazor formulářů
Poznámka:
Toto není nejnovější verze tohoto článku. Aktuální verzi najdete ve verzi .NET 8 tohoto článku.
Důležité
Tyto informace se týkají předběžného vydání produktu, který může být podstatně změněn před komerčním vydáním. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.
Aktuální verzi najdete ve verzi .NET 8 tohoto článku.
Tento článek vysvětluje, jak používat vazbu ve Blazor formulářích.
EditForm
/EditContext
model
EditContext Vytvoří EditForm na základě přiřazeného objektu kaskádovou hodnotu pro ostatní komponenty ve formuláři. Sleduje EditContext metadata procesu úprav, včetně toho, která pole formuláře byla změněna, a aktuální ověřovací zprávy. Přiřazení k formuláři EditForm.Model nebo k EditForm.EditContext datům může vytvořit vazbu.
Vazby modelu
Přiřazení:EditForm.Model
<EditForm ... Model="Model" ...>
...
</EditForm>
@code {
[SupplyParameterFromForm]
public 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();
}
Poznámka:
Většina příkladů modelu formulářů tohoto článku spojuje formuláře s vlastnostmi jazyka C#, ale vazba pole jazyka C# je podporována také.
Kontextová vazba
Přiřazení:EditForm.EditContext
<EditForm ... EditContext="editContext" ...>
...
</EditForm>
@code {
private EditContext? editContext;
[SupplyParameterFromForm]
public 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);
}
}
Přiřaďte k ModelEditContextobjektu .EditForm Pokud jsou oba přiřazené, vyvolá se chyba za běhu.
Podporované typy
Vazba podporuje:
- Primitivní typy
- Kolekce
- Komplexní typy
- Rekurzivní typy
- Typy s konstruktory
- Výčty
Vazby [DataMember]
[IgnoreDataMember]
modelu můžete přizpůsobit také pomocí atributů. Pomocí těchto atributů můžete přejmenovat vlastnosti, ignorovat vlastnosti a označit vlastnosti jako povinné.
Další možnosti vazby
Při volání AddRazorComponentsjsou k dispozici RazorComponentsServiceOptions další možnosti vazby modelu:
- MaxFormMappingCollectionSize: Maximální počet prvků povolených v kolekci formulářů.
- MaxFormMappingRecursionDepth: Maximální povolená hloubka při rekurzivním mapování dat formuláře.
- MaxFormMappingErrorCount: Maximální počet chyb povolených při mapování dat formuláře.
- MaxFormMappingKeySize: Maximální velikost vyrovnávací paměti použité ke čtení datových klíčů formuláře.
Následující příklad ukazuje výchozí hodnoty přiřazené architekturou:
builder.Services.AddRazorComponents(options =>
{
options.FormMappingUseCurrentCulture = true;
options.MaxFormMappingCollectionSize = 1024;
options.MaxFormMappingErrorCount = 200;
options.MaxFormMappingKeySize = 1024 * 2;
options.MaxFormMappingRecursionDepth = 64;
}).AddInteractiveServerComponents();
Názvy formulářů
Pomocí parametru FormName přiřaďte název formuláře. Názvy formulářů musí být jedinečné pro vytvoření vazby dat modelu. Následující formulář má název RomulanAle
:
<EditForm ... FormName="RomulanAle" ...>
...
</EditForm>
Zadání názvu formuláře:
- Vyžaduje se pro všechny formuláře odeslané staticky vykreslenými komponentami na straně serveru.
- Nevyžaduje se u formulářů odesílaných interaktivně vykreslenými komponentami, které zahrnují formuláře v Blazor WebAssembly aplikacích a komponentách s interaktivním režimem vykreslování. Doporučujeme však zadat jedinečný název formuláře pro každý formulář, aby se zabránilo chybám při publikování za běhu formuláře, pokud dojde k vyřazení interaktivity formuláře.
Název formuláře je kontrolován pouze v případech, kdy se formulář publikuje do koncového bodu jako tradiční požadavek HTTP POST ze staticky vykreslené součásti na straně serveru. Architektura nevyvolá výjimku v okamžiku vykreslení formuláře, ale pouze v okamžiku, kdy přijde http POST a nezadá název formuláře.
Ve výchozím nastavení je nad kořenovou komponentou aplikace obor formuláře bez názvu (prázdný řetězec), který stačí, když v aplikaci nedojde ke kolizi názvu formuláře. Pokud jsou možné kolize názvů formulářů, například při zahrnutí formuláře z knihovny a nemáte žádnou kontrolu nad názvem formuláře používaným vývojářem knihovny, zadejte obor názvu formuláře s FormMappingScope komponentou v Blazor hlavním projektu webové aplikace.
V následujícím příkladu HelloFormFromLibrary
má komponenta název Hello
formuláře a je v knihovně.
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]
public string? Name { get; set; }
private void Submit() => submitted = true;
}
Následující NamedFormsWithScope
komponenta používá komponentu knihovny HelloFormFromLibrary
a má také formulář s názvem Hello
. Název FormMappingScope oboru komponenty je ParentContext
určen pro všechny formuláře zadané komponentou HelloFormFromLibrary
. I když oba formuláře v tomto příkladu mají název formuláře (Hello
), názvy formulářů nejsou kolidovány a události jsou směrovány do správného formuláře pro události POST formuláře.
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]
public string? Name { get; set; }
private void Submit() => submitted = true;
}
Zadání parametru z formuláře ([SupplyParameterFromForm]
)
Atribut [SupplyParameterFromForm]
označuje, že hodnota přidružené vlastnosti by měla být zadána z dat formuláře pro formulář. Data v požadavku, která odpovídají názvu vlastnosti, jsou svázaná s vlastností. Vstupy založené na InputBase<TValue>
generování názvů hodnot formuláře, které odpovídají názvům Blazor , které se používají pro vazbu modelu.
Pro atribut můžete zadat následující parametry vazby [SupplyParameterFromForm]
formuláře:
- Name: Získá nebo nastaví název parametru. Název se používá k určení předpony, která se má použít ke shodě dat formuláře, a rozhodnutí, zda má být hodnota vázána nebo ne.
- FormName: Získá nebo nastaví název obslužné rutiny. Název se používá ke shodě parametru s formulářem podle názvu formuláře, aby se rozhodl, zda je potřeba hodnotu vázat nebo ne.
Následující příklad nezávisle vytvoří vazbu dvou formulářů na jejich modely podle názvu formuláře.
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")]
public Holodeck? Model1 { get; set; }
[SupplyParameterFromForm(FormName = "Holodeck2")]
public 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; }
}
}
Vnoření a vytvoření vazby formulářů
Následující doprovodné materiály ukazují, jak vnořit a svázat podřízené formuláře.
Následující třída podrobností o expediciShipDetails
obsahuje popis a délku podformulář.
ShipDetails.cs
:
namespace BlazorSample;
public class ShipDetails
{
public string? Description { get; set; }
public int? Length { get; set; }
}
Následující Ship
třída pojmenuje identifikátor (Id
) a obsahuje podrobnosti o expedici.
Ship.cs
:
namespace BlazorSample
{
public class Ship
{
public string? Id { get; set; }
public ShipDetails Details { get; set; } = new();
}
}
Následující podformulář slouží k úpravě hodnot ShipDetails
typu. To je implementováno děděním Editor<T> v horní části komponenty. Editor<T> zajišťuje, aby podřízená komponenta vygenerovala správné názvy polí formuláře na základě modelu (T
), kde T
v následujícím příkladu je 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>
Hlavní formulář je vázán na Ship
třídu. Komponenta StarshipSubform
slouží k úpravě podrobností o expedici svázané 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]
public 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);
}
}
Pokročilé scénáře chyb mapování formulářů
Architektura vytvoří instanci formuláře a naplní FormMappingContext ho, což je kontext přidružený k operaci mapování daného formuláře. Vytvoří instanci každého oboru mapování (definovaného komponentouFormMappingScope).FormMappingContext Pokaždé, když se [SupplyParameterFromForm]
zeptá kontextu na hodnotu, architektura naplní FormMappingContext pokusnou hodnotou a všechny chyby mapování.
Vývojáři se neočekává, že budou pracovat FormMappingContext přímo, protože se jedná hlavně o zdroj dat pro InputBase<TValue>, EditContexta další interní implementace, které ukazují chyby mapování jako chyby ověřování. V pokročilých vlastních scénářích můžou vývojáři přistupovat FormMappingContext přímo jako k zápisu vlastního [CascadingParameter]
kódu, který využívá pokusy o hodnoty a chyby mapování.
Přepínače
Příklad v této části je založen na Starfleet Starship Database
formuláři (Starship3
komponentě) části Příklad formuláře tohoto článku.
Do aplikace přidejte následující enum
typy . Vytvořte nový soubor pro jejich uložení nebo je přidejte do Starship.cs
souboru.
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
Zpřístupnění třídy pro:
Starship
model inStarship.cs
(napříkladusing static ComponentEnums;
).Starfleet Starship Database
form () (Starship3.razor
například@using static ComponentEnums
).
Pomocí InputRadio<TValue> komponent InputRadioGroup<TValue> vytvořte skupinu přepínačů. V následujícím příkladu Starship
se vlastnosti přidají do modelu popsaného v části Příklad formuláře článku o vstupních komponentách :
[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;
Aktualizujte Starfleet Starship Database
formulář (Starship3
součást) části Příklad formuláře článku Vstupní komponenty. Přidejte komponenty, které se mají vytvořit:
- Skupina přepínačů pro výrobce lodi.
- Vnořená skupina přepínačů pro barvu motoru a lodi.
Poznámka:
Vnořené skupiny přepínačů se často nepoužívají ve formulářích, protože můžou vést k neuspořádanému rozložení ovládacích prvků formuláře, které můžou uživatele zmást. Existují však případy, kdy mají smysl v návrhu uživatelského rozhraní, například v následujícím příkladu, který spáruje doporučení pro dva vstupy uživatelů, modul lodí a barvu lodi. Ověření formuláře vyžaduje jeden modul a jednu barvu. Rozložení formuláře používá vnořené InputRadioGroup<TValue>čáry ke spárování motoru a doporučení barev. Uživatel ale může zkombinovat libovolný modul s libovolnou barvou a odeslat formulář.
Poznámka:
Ujistěte se, že ComponentEnums
je třída dostupná pro komponentu v následujícím příkladu:
@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>
Poznámka:
Pokud Name
je vynechán, InputRadio<TValue> komponenty jsou seskupené podle jejich nejnovějšího nadřazeného objektu.
Pokud jste implementovali předchozí kód v Starship3
komponentě příklad formuláře oddílu Vstupní komponenty článku, aktualizujte protokolování pro metoduSubmit
:Razor
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);
Při práci s přepínači ve formuláři se datová vazba zpracovává jinak než jiné prvky, protože přepínače se vyhodnocují jako skupina. Hodnota každého přepínače je pevná, ale hodnota skupiny přepínačů je hodnota vybraného přepínače. Následující příklad ukazuje, jak:
- Zpracování datové vazby pro skupinu přepínačů
- Podpora ověřování pomocí vlastní InputRadio<TValue> komponenty
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;
}
}
}
Další informace o parametrech obecného typu (@typeparam
) najdete v následujících článcích:
- Referenční informace k syntaxi Razor pro ASP.NET Core
- komponenty ASP.NET Core Razor
- Komponenty ASP.NET Core Blazor bez vizuálního vzhledu
Použijte následující ukázkový model.
StarshipModel.cs
:
using System.ComponentModel.DataAnnotations;
namespace BlazorServer80
{
public class Model
{
[Range(1, 5)]
public int Rating { get; set; }
}
}
Následující RadioButtonExample
komponenta používá předchozí InputRadio
komponentu k získání a ověření hodnocení od uživatele:
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");
}
}
Váš názor
https://aka.ms/ContentUserFeedback.
Připravujeme: V průběhu roku 2024 budeme postupně vyřazovat problémy z GitHub coby mechanismus zpětné vazby pro obsah a nahrazovat ho novým systémem zpětné vazby. Další informace naleznete v tématu:Odeslat a zobrazit názory pro