Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Not
Bu, bu makalenin en son sürümü değildir. Geçerli sürüm için bu makalenin .NET 10 sürümüne bakın.
Uyarı
ASP.NET Core'un bu sürümü artık desteklenmiyor. Daha fazla bilgi için bkz . .NET ve .NET Core Destek İlkesi. Geçerli sürüm için bu makalenin .NET 9 sürümüne bakın.
Bu makalede, uygulamalardaki Razor bileşenler ve DOM öğeleri için Blazor veri bağlama özellikleri açıklanmaktadır.
Bağlama özellikleri
Razorbileşenleri alan, özellik veya @bind ifade değeriyle RazorRazor yönerge özniteliğiyle veri bağlama özellikleri sağlar.
Aşağıdaki örnek bağlar:
-
<input>C#inputValuealanına bir öğe değeri. - C#
<input>özelliğine ikinciInputValuebir öğe değeri.
Bir <input> öğe odağı kaybettiğinde, ilişkili alanı veya özelliği güncelleştirilir.
Bind.razor:
@page "/bind"
<PageTitle>Bind</PageTitle>
<h1>Bind Example</h1>
<p>
<label>
inputValue:
<input @bind="inputValue" />
</label>
</p>
<p>
<label>
InputValue:
<input @bind="InputValue" />
</label>
</p>
<ul>
<li><code>inputValue</code>: @inputValue</li>
<li><code>InputValue</code>: @InputValue</li>
</ul>
@code {
private string? inputValue;
private string? InputValue { get; set; }
}
@page "/bind"
<PageTitle>Bind</PageTitle>
<h1>Bind Example</h1>
<p>
<label>
inputValue:
<input @bind="inputValue" />
</label>
</p>
<p>
<label>
InputValue:
<input @bind="InputValue" />
</label>
</p>
<ul>
<li><code>inputValue</code>: @inputValue</li>
<li><code>InputValue</code>: @InputValue</li>
</ul>
@code {
private string? inputValue;
private string? InputValue { get; set; }
}
@page "/bind"
<p>
<input @bind="inputValue" />
</p>
<p>
<input @bind="InputValue" />
</p>
<ul>
<li><code>inputValue</code>: @inputValue</li>
<li><code>InputValue</code>: @InputValue</li>
</ul>
@code {
private string? inputValue;
private string? InputValue { get; set; }
}
@page "/bind"
<p>
<input @bind="inputValue" />
</p>
<p>
<input @bind="InputValue" />
</p>
<ul>
<li><code>inputValue</code>: @inputValue</li>
<li><code>InputValue</code>: @InputValue</li>
</ul>
@code {
private string? inputValue;
private string? InputValue { get; set; }
}
@page "/bind"
<p>
<input @bind="inputValue" />
</p>
<p>
<input @bind="InputValue" />
</p>
<ul>
<li><code>inputValue</code>: @inputValue</li>
<li><code>InputValue</code>: @InputValue</li>
</ul>
@code {
private string inputValue;
private string InputValue { get; set; }
}
@page "/bind"
<p>
<input @bind="inputValue" />
</p>
<p>
<input @bind="InputValue" />
</p>
<ul>
<li><code>inputValue</code>: @inputValue</li>
<li><code>InputValue</code>: @InputValue</li>
</ul>
@code {
private string inputValue;
private string InputValue { get; set; }
}
Metin kutusu kullanıcı arabiriminde yalnızca bileşen işlendiğinde güncelleştirilir, alanın veya özelliğin değerinin değiştirilmesine yanıt olarak güncelleştirilmez. Bileşenler, olay işleyicisi kodu yürütülürken kendilerini işlediğinden, alan ve özellik güncelleştirmeleri genellikle bir olay işleyicisi tetiklendikten hemen sonra kullanıcı arabirimine yansıtılır.
Veri bağlamanın HTML'de nasıl oluştuğunu gösteren bir örnek olarak, aşağıdaki örnek özelliği ikinci InputValue öğenin <input> ve value özniteliklerine (onchange ) bağlarchange.
Aşağıdaki örnekteki ikinci <input> öğe bir kavram gösterimidir ve bileşenlerdeki Razor verileri nasıl bağlamanız gerektiğini önermek için tasarlanmamıştır.
BindTheory.razor:
@page "/bind-theory"
<PageTitle>Bind Theory</PageTitle>
<h1>Bind Theory Example</h1>
<p>
<label>
Normal Blazor binding:
<input @bind="InputValue" />
</label>
</p>
<p>
<label>
Demonstration of equivalent HTML binding:
<input value="@InputValue" @onchange="@((ChangeEventArgs __e) =>
InputValue = __e?.Value?.ToString())" />
</label>
</p>
<p>
<code>InputValue</code>: @InputValue
</p>
@code {
private string? InputValue { get; set; }
}
@page "/bind-theory"
<PageTitle>Bind Theory</PageTitle>
<h1>Bind Theory Example</h1>
<p>
<label>
Normal Blazor binding:
<input @bind="InputValue" />
</label>
</p>
<p>
<label>
Demonstration of equivalent HTML binding:
<input value="@InputValue" @onchange="@((ChangeEventArgs __e) =>
InputValue = __e?.Value?.ToString())" />
</label>
</p>
<p>
<code>InputValue</code>: @InputValue
</p>
@code {
private string? InputValue { get; set; }
}
@page "/bind-theory"
<p>
<label>
Normal Blazor binding:
<input @bind="InputValue" />
</label>
</p>
<p>
<label>
Demonstration of equivalent HTML binding:
<input value="@InputValue"
@onchange="@((ChangeEventArgs __e) => InputValue = __e?.Value?.ToString())" />
</label>
</p>
<p>
<code>InputValue</code>: @InputValue
</p>
@code {
private string? InputValue { get; set; }
}
@page "/bind-theory"
<p>
<label>
Normal Blazor binding:
<input @bind="InputValue" />
</label>
</p>
<p>
<label>
Demonstration of equivalent HTML binding:
<input value="@InputValue"
@onchange="@((ChangeEventArgs __e) => InputValue = __e?.Value?.ToString())" />
</label>
</p>
<p>
<code>InputValue</code>: @InputValue
</p>
@code {
private string? InputValue { get; set; }
}
@page "/bind-theory"
<p>
<label>
Normal Blazor binding:
<input @bind="InputValue" />
</label>
</p>
<p>
<label>
Demonstration of equivalent HTML binding:
<input value="@InputValue"
@onchange="@((ChangeEventArgs __e) => InputValue = __e.Value.ToString())" />
</label>
</p>
<p>
<code>InputValue</code>: @InputValue
</p>
@code {
private string InputValue { get; set; }
}
@page "/bind-theory"
<p>
<label>
Normal Blazor binding:
<input @bind="InputValue" />
</label>
</p>
<p>
<label>
Demonstration of equivalent HTML binding:
<input value="@InputValue"
@onchange="@((ChangeEventArgs __e) => InputValue = __e.Value.ToString())" />
</label>
</p>
<p>
<code>InputValue</code>: @InputValue
</p>
@code {
private string InputValue { get; set; }
}
BindTheory Bileşen işlendiğinde, value HTML tanıtım <input> öğesinin özelliğinden InputValue gelir. Kullanıcı metin kutusuna bir değer girip öğe odağını değiştirdiğinde, onchange olay tetiklenir ve InputValue özellik değiştirilen değere ayarlanır. Gerçekte kod yürütme daha karmaşıktır çünkü @bind tür dönüştürmelerinin gerçekleştirildiği durumları işler. Genel olarak, @bind bir ifadenin geçerli değerini özniteliğiyle value<input> ilişkilendirir ve kayıtlı işleyiciyi kullanarak değişiklikleri işler.
Yer tutucu için DOM olayına sahip bir @bind:event="{EVENT}" öznitelik ekleyerek diğer DOM olaylarında {EVENT} bir özellik veya alan bağlayın. Aşağıdaki örnek, öğenin olayı (InputValue) tetiklendiğinde özelliğini <input> öğenin oninput değerine bağlarinput.
onchange Öğenin odağı kaybettiğinde tetiklenen () olayındanchange farklı olarak, oninput metin kutusunun değeri değiştiğinde (input) tetikler.
Page/BindEvent.razor:
@page "/bind-event"
<PageTitle>Bind Event</PageTitle>
<h1>Bind Event Example</h1>
<p>
<label>
InputValue:
<input @bind="InputValue" @bind:event="oninput" />
</label>
</p>
<p>
<code>InputValue</code>: @InputValue
</p>
@code {
private string? InputValue { get; set; }
}
@page "/bind-event"
<PageTitle>Bind Event</PageTitle>
<h1>Bind Event Example</h1>
<p>
<label>
InputValue:
<input @bind="InputValue" @bind:event="oninput" />
</label>
</p>
<p>
<code>InputValue</code>: @InputValue
</p>
@code {
private string? InputValue { get; set; }
}
@page "/bind-event"
<p>
<input @bind="InputValue" @bind:event="oninput" />
</p>
<p>
<code>InputValue</code>: @InputValue
</p>
@code {
private string? InputValue { get; set; }
}
@page "/bind-event"
<p>
<input @bind="InputValue" @bind:event="oninput" />
</p>
<p>
<code>InputValue</code>: @InputValue
</p>
@code {
private string? InputValue { get; set; }
}
@page "/bind-event"
<p>
<input @bind="InputValue" @bind:event="oninput" />
</p>
<p>
<code>InputValue</code>: @InputValue
</p>
@code {
private string InputValue { get; set; }
}
@page "/bind-event"
<p>
<input @bind="InputValue" @bind:event="oninput" />
</p>
<p>
<code>InputValue</code>: @InputValue
</p>
@code {
private string InputValue { get; set; }
}
Razor öznitelik bağlama büyük/küçük harfe duyarlıdır:
-
@bindve@bind:eventgeçerlidir. -
@Bind/@Bind:Event(büyük harflerBveE) veya@BIND/@BIND:EVENT(tüm büyük harfler) geçersizdir.
Bağlamadan sonra zaman uyumsuz mantık yürütmek için, @bind:after="{DELEGATE}"yer tutucunun {DELEGATE} bir C# temsilcisi (yöntem) olduğu kullanın. Atanan C# temsilcisi, ilişkili değer zaman uyumlu olarak atanana kadar yürütülemez.
ile bir olay geri çağırma parametresi (EventCallback/EventCallback<T>) kullanılması desteklenmez.@bind:after Bunun yerine, veya ActionTaskdeğerini döndüren bir @bind:after yöntem geçirin.
Aşağıdaki örnekte:
- Her
<input>öğeninvaluealanı zaman uyumlu olarak bağlıdırsearchText. -
PerformSearchyöntemi zaman uyumsuz olarak yürütülür:- Değer değiştirildikten sonra ilk kutu odağı (
onchangeolay) kaybettiğinde. - İkinci kutudaki her tuş vuruşunun (
oninputolay) ardından.
- Değer değiştirildikten sonra ilk kutu odağı (
-
PerformSearcharama sonuçlarını döndürmek için zaman uyumsuz bir yöntemle (FetchAsync) bir hizmeti çağırır.
@inject ISearchService SearchService
<input @bind="searchText" @bind:after="PerformSearch" />
<input @bind="searchText" @bind:event="oninput" @bind:after="PerformSearch" />
@code {
private string? searchText;
private string[]? searchResult;
private async Task PerformSearch() =>
searchResult = await SearchService.FetchAsync(searchText);
}
Ek örnekler
BindAfter.razor:
@page "/bind-after"
@using Microsoft.AspNetCore.Components.Forms
<h1>Bind After Examples</h1>
<h2>Elements</h2>
<input type="text" @bind="text" @bind:after="() => { }" />
<input type="text" @bind="text" @bind:after="After" />
<input type="text" @bind="text" @bind:after="AfterAsync" />
<h2>Components</h2>
<InputText @bind-Value="text" @bind-Value:after="() => { }" />
<InputText @bind-Value="text" @bind-Value:after="After" />
<InputText @bind-Value="text" @bind-Value:after="AfterAsync" />
@code {
private string text = "";
private void After() {}
private Task AfterAsync() { return Task.CompletedTask; }
}
Bileşen hakkında InputText daha fazla bilgi için bkz . ASP.NET Core Blazor giriş bileşenleri.
Bileşenler, @bind veya :get değiştiricisi olan bir çift :set özniteliği tanımlayarak iki yönlü veri bağlamayı destekler. Aşağıdaki örneklerde yer alan {PARAMETER} yer tutucusu bir bileşen parametresini bağlamak için kullanılır:
-
@bind:get/@bind-{PARAMETER}:get: Bağlanacak değeri belirtir. -
@bind:set/@bind-{PARAMETER}:set: Değer değiştiğinde için bir geri çağırma belirtir.
:get ve :set değiştiricileri her zaman birlikte kullanılır.
:get
/
:set bağlama ile, dom'a uygulanmadan önce bir değer değişikliğine tepki verebilir ve gerekirse uygulanan değeri değiştirebilirsiniz.
@bind:event="{EVENT}" yer tutucusunun bir DOM olayı olarak kullanıldığı {EVENT} öznitelik bağlama durumunda, DOM güncellendikten sonra bildirimi alırsınız ve bağlama esnasında uygulanan değerin değiştirilmesi mümkün değildir.
Aşağıdaki
BindGetSet.razor:
@page "/bind-get-set"
@using Microsoft.AspNetCore.Components.Forms
<h1>Bind Get Set Examples</h1>
<h2>Elements</h2>
<input type="text" @bind:get="text" @bind:set="(value) => { text = value; }" />
<input type="text" @bind:get="text" @bind:set="Set" />
<input type="text" @bind:get="text" @bind:set="SetAsync" />
<h2>Components</h2>
<InputText @bind-Value:get="text" @bind-Value:set="(value) => { text = value; }" />
<InputText @bind-Value:get="text" @bind-Value:set="Set" />
<InputText @bind-Value:get="text" @bind-Value:set="SetAsync" />
@code {
private string text = string.Empty;
private void Set(string value)
{
text = value;
}
private Task SetAsync(string value)
{
text = value;
return Task.CompletedTask;
}
}
Bileşen hakkında InputText daha fazla bilgi için bkz . ASP.NET Core Blazor giriş bileşenleri.
ve @bind:getöğesinin @bind:set başka bir örnek kullanımı için, bu makalenin devamında yer alan İkiden fazla bileşen arasında bağlama bölümüne bakın.
Razor öznitelik bağlama büyük/küçük harfe duyarlıdır:
-
@bind,@bind:eventve@bind:aftergeçerli. -
@Bind/@bind:Event/@bind:aftEr(büyük harfler) veya@BIND/@BIND:EVENT/@BIND:AFTER(tüm büyük harfler) geçersizdir.
Değiştiricileri kullanma @bind:get/@bind:set ve iki yönlü veri bağlama için olay işleyicilerinden kaçınma
olay işleyicisi ile iki yönlü veri bağlaması uygulanamaz. İki yönlü veri bağlama için değiştiricileri kullanın @bind:get/@bind:set .
Olay işleyicisi kullanarak iki yönlü veri bağlama için aşağıdaki işlevsiz yaklaşımı göz önünde bulundurun:
<p>
<input value="@inputValue" @oninput="OnInput" />
</p>
<p>
<code>inputValue</code>: @inputValue
</p>
@code {
private string? inputValue;
private void OnInput(ChangeEventArgs args)
{
var newValue = args.Value?.ToString() ?? string.Empty;
inputValue = newValue.Length > 4 ? "Long!" : newValue;
}
}
Olay işleyicisi OnInput değerini, dördüncü karakter sağlandıktan sonra olarak güncelleştirir inputValueLong! . Ancak kullanıcı, kullanıcı arabirimindeki öğe değerine karakter eklemeye devam edebilir. değeri inputValue , her tuş vuruşuyla öğenin değerine bağlı değildir. Yukarıdaki örnek yalnızca tek yönlü veri bağlama özelliğine sahiptir.
Bu davranışın nedeni, kodunuzun Blazor olay işleyicisindeki değerini inputValue değiştirmeyi amaçladığının farkında olmamanızdır.
Blazor dom öğesi değerleri ve .NET değişken değerleri, söz dizimi ile @bind bağlı olmadığı sürece eşleşecek şekilde zorlamaya çalışmaz. önceki sürümlerinde Blazor, iki yönlü veri bağlama, öğesini bir özelliğe bağlayarak ve özelliğin değerini ayarlayıcısıyla denetleyerek uygulanır. .NET 7 veya sonraki sürümlerindeki ASP.NET Core'da, @bind:get/@bind:set sonraki örnekte gösterildiği gibi iki yönlü veri bağlama uygulamak için değiştirici söz dizimi kullanılır.
İki yönlü veri bağlama için kullanarak @bind:getaşağıdaki / göz önünde bulundurun:
<p>
<input @bind:event="oninput" @bind:get="inputValue" @bind:set="OnInput" />
</p>
<p>
<code>inputValue</code>: @inputValue
</p>
@code {
private string? inputValue;
private void OnInput(string value)
{
var newValue = value ?? string.Empty;
inputValue = newValue.Length > 4 ? "Long!" : newValue;
}
}
Değiştiricileri kullanarak @bind:get/@bind:sethem öğesinin inputValue@bind:set temel değerini denetler hem de öğesinin değerini inputValue aracılığıyla @bind:getöğesinin değerine bağlar. Yukarıdaki örnekte, iki yönlü veri bağlama uygulamak için doğru yaklaşım gösterilmektedir.
C# get ve set erişimcilerle bir özelliğe bağlama
C# get ve set erişimciler , aşağıdaki DecimalBinding bileşenin gösterdiği gibi özel bağlama biçimi davranışı oluşturmak için kullanılabilir. Bileşen, bir öğeye bir özellik (<input>) yoluyla en fazla üç ondalık basamak string içeren pozitif veya negatif bir DecimalValue ondalık bağlar.
DecimalBinding.razor:
@page "/decimal-binding"
@using System.Globalization
<PageTitle>Decimal Binding</PageTitle>
<h1>Decimal Binding Example</h1>
<p>
<label>
Decimal value (±0.000 format):
<input @bind="DecimalValue" />
</label>
</p>
<p>
<code>decimalValue</code>: @decimalValue
</p>
@code {
private decimal decimalValue = 1.1M;
private NumberStyles style =
NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign;
private CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
private string DecimalValue
{
get => decimalValue.ToString("0.000", culture);
set
{
if (Decimal.TryParse(value, style, culture, out var number))
{
decimalValue = Math.Round(number, 3);
}
}
}
}
@page "/decimal-binding"
@using System.Globalization
<PageTitle>Decimal Binding</PageTitle>
<h1>Decimal Binding Example</h1>
<p>
<label>
Decimal value (±0.000 format):
<input @bind="DecimalValue" />
</label>
</p>
<p>
<code>decimalValue</code>: @decimalValue
</p>
@code {
private decimal decimalValue = 1.1M;
private NumberStyles style =
NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign;
private CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
private string DecimalValue
{
get => decimalValue.ToString("0.000", culture);
set
{
if (Decimal.TryParse(value, style, culture, out var number))
{
decimalValue = Math.Round(number, 3);
}
}
}
}
@page "/decimal-binding"
@using System.Globalization
<p>
<label>
Decimal value (±0.000 format):
<input @bind="DecimalValue" />
</label>
</p>
<p>
<code>decimalValue</code>: @decimalValue
</p>
@code {
private decimal decimalValue = 1.1M;
private NumberStyles style =
NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign;
private CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
private string DecimalValue
{
get => decimalValue.ToString("0.000", culture);
set
{
if (Decimal.TryParse(value, style, culture, out var number))
{
decimalValue = Math.Round(number, 3);
}
}
}
}
@page "/decimal-binding"
@using System.Globalization
<p>
<label>
Decimal value (±0.000 format):
<input @bind="DecimalValue" />
</label>
</p>
<p>
<code>decimalValue</code>: @decimalValue
</p>
@code {
private decimal decimalValue = 1.1M;
private NumberStyles style =
NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign;
private CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
private string DecimalValue
{
get => decimalValue.ToString("0.000", culture);
set
{
if (Decimal.TryParse(value, style, culture, out var number))
{
decimalValue = Math.Round(number, 3);
}
}
}
}
@page "/decimal-binding"
@using System.Globalization
<p>
<label>
Decimal value (±0.000 format):
<input @bind="DecimalValue" />
</label>
</p>
<p>
<code>decimalValue</code>: @decimalValue
</p>
@code {
private decimal decimalValue = 1.1M;
private NumberStyles style =
NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign;
private CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
private string DecimalValue
{
get => decimalValue.ToString("0.000", culture);
set
{
if (Decimal.TryParse(value, style, culture, out var number))
{
decimalValue = Math.Round(number, 3);
}
}
}
}
@page "/decimal-binding"
@using System.Globalization
<p>
<label>
Decimal value (±0.000 format):
<input @bind="DecimalValue" />
</label>
</p>
<p>
<code>decimalValue</code>: @decimalValue
</p>
@code {
private decimal decimalValue = 1.1M;
private NumberStyles style =
NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign;
private CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
private string DecimalValue
{
get => decimalValue.ToString("0.000", culture);
set
{
if (Decimal.TryParse(value, style, culture, out var number))
{
decimalValue = Math.Round(number, 3);
}
}
}
}
Not
Birden çok bileşen arasında, get/set erişimcilerine sahip bir özelliğe çift yönlü bağlama, özelliğin ayarlayıcısında Task tarafından döndürülen EventCallback.InvokeAsync değerinin atılmasını gerektirir. İki yönlü veri bağlama için değiştiricileri kullanmanızı @bind:get/@bind:set öneririz. Daha fazla bilgi için bu makalenin önceki bölümlerinde
Not
Erişimcileri olan get/set bir özelliğe iki yönlü bağlama, tarafından Taskdöndürülenin EventCallback.InvokeAsync atılması gerekir. Örneğin, ikiden fazla bileşen arasında bağlama @bind:get/@bind:set öneririz.
Öğelerle <select> birden çok seçenek seçimi
Bağlama, öğelerle multiple seçenek seçimini destekler<select>. Olay, @onchange seçilen öğelerin bir dizisini olay bağımsız değişkenleri (ChangeEventArgs) aracılığıyla sağlar. Değer bir dizi türüne bağlı olmalıdır.
BindMultipleInput.razor:
@page "/bind-multiple-input"
<h1>Bind Multiple <code>input</code>Example</h1>
<p>
<label>
Select one or more cars:
<select @onchange="SelectedCarsChanged" multiple>
<option value="audi">Audi</option>
<option value="jeep">Jeep</option>
<option value="opel">Opel</option>
<option value="saab">Saab</option>
<option value="volvo">Volvo</option>
</select>
</label>
</p>
<p>
Selected Cars: @string.Join(", ", SelectedCars)
</p>
<p>
<label>
Select one or more cities:
<select @bind="SelectedCities" multiple>
<option value="bal">Baltimore</option>
<option value="la">Los Angeles</option>
<option value="pdx">Portland</option>
<option value="sf">San Francisco</option>
<option value="sea">Seattle</option>
</select>
</label>
</p>
<span>
Selected Cities: @string.Join(", ", SelectedCities)
</span>
@code {
public string[] SelectedCars { get; set; } = [];
public string[] SelectedCities { get; set; } = [ "bal", "sea" ];
private void SelectedCarsChanged(ChangeEventArgs e)
{
if (e.Value is not null)
{
SelectedCars = (string[])e.Value;
}
}
}
@page "/bind-multiple-input"
<h1>Bind Multiple <code>input</code>Example</h1>
<p>
<label>
Select one or more cars:
<select @onchange="SelectedCarsChanged" multiple>
<option value="audi">Audi</option>
<option value="jeep">Jeep</option>
<option value="opel">Opel</option>
<option value="saab">Saab</option>
<option value="volvo">Volvo</option>
</select>
</label>
</p>
<p>
Selected Cars: @string.Join(", ", SelectedCars)
</p>
<p>
<label>
Select one or more cities:
<select @bind="SelectedCities" multiple>
<option value="bal">Baltimore</option>
<option value="la">Los Angeles</option>
<option value="pdx">Portland</option>
<option value="sf">San Francisco</option>
<option value="sea">Seattle</option>
</select>
</label>
</p>
<span>
Selected Cities: @string.Join(", ", SelectedCities)
</span>
@code {
public string[] SelectedCars { get; set; } = new string[] { };
public string[] SelectedCities { get; set; } = new[] { "bal", "sea" };
private void SelectedCarsChanged(ChangeEventArgs e)
{
if (e.Value is not null)
{
SelectedCars = (string[])e.Value;
}
}
}
Boş dizelerin ve null değerlerin veri bağlamada nasıl işleneceğini öğrenmek için C# nesne <select> değerlerine öğe seçeneklerini bağlama null bölümüne bakın.
Öğe seçeneklerini C# nesne <select> değerlerine bağlama null
Öğe seçenek değerini C# nesne <select> değeri olarak temsil null etmenin mantıklı bir yolu yoktur, çünkü:
- HTML özniteliklerinin değerleri olamaz
null. HTML'deki ilenullen yakın eşdeğer, öğesindenvalueHTML<option>özniteliğinin olmamasıdır. - Özniteliği olmayan
<option>birvalueöğesini seçerken, tarayıcı değeri bu öğenin metin içeriği<option>değerlendirir.
Çerçeve, Blazor aşağıdakileri içereceğinden varsayılan davranışı gizlemeye çalışmaz:
- Çerçevede özel durum geçici çözüm zinciri oluşturma.
- Geçerli çerçeve davranışında hataya neden olan değişiklikler.
HTML'deki en makul null eşdeğer boş bir dizedirvalue. Çerçeve, Blazor bir nulldeğerine iki yönlü bağlama için boş dize dönüştürmelerini işler<select>.
Ayrıştırılamaz değerler
Kullanıcı veriye bağlı bir öğeye ayrıştırılamaz bir değer sağladığında, bağlama olayı tetiklendiğinde ayrıştırılamaz değer otomatik olarak önceki değerine geri döndürülür.
Bir öğenin başlangıç değeri <input>olan bir int türe bağlı olduğu 123 aşağıdaki bileşeni göz önünde bulundurun.
UnparsableValues.razor:
@page "/unparsable-values"
<PageTitle>Unparsable Values</PageTitle>
<h1>Unparsable Values Example</h1>
<p>
<label>
inputValue:
<input @bind="inputValue" />
</label>
</p>
<p>
<code>inputValue</code>: @inputValue
</p>
@code {
private int inputValue = 123;
}
@page "/unparsable-values"
<PageTitle>Unparsable Values</PageTitle>
<h1>Unparsable Values Example</h1>
<p>
<label>
inputValue:
<input @bind="inputValue" />
</label>
</p>
<p>
<code>inputValue</code>: @inputValue
</p>
@code {
private int inputValue = 123;
}
@page "/unparseable-values"
<p>
<input @bind="inputValue" />
</p>
<p>
<code>inputValue</code>: @inputValue
</p>
@code {
private int inputValue = 123;
}
@page "/unparseable-values"
<p>
<input @bind="inputValue" />
</p>
<p>
<code>inputValue</code>: @inputValue
</p>
@code {
private int inputValue = 123;
}
@page "/unparseable-values"
<p>
<input @bind="inputValue" />
</p>
<p>
<code>inputValue</code>: @inputValue
</p>
@code {
private int inputValue = 123;
}
@page "/unparseable-values"
<p>
<input @bind="inputValue" />
</p>
<p>
<code>inputValue</code>: @inputValue
</p>
@code {
private int inputValue = 123;
}
Bağlama, öğenin onchange olayı için geçerlidir. Kullanıcı metin kutusunun girdisinin 123.45 değerini olarak güncelleştirir ve odağı değiştirirse, tetiklendiğinde 123 öğenin değeri geri döndürülüronchange. Değeri özgün değeri 123.45123yerine reddedildiğinde, kullanıcı değerinin kabul edilmediğini anlar.
oninput() olayı@bind:event="oninput" için, ayrıştırılamaz bir değer getiren herhangi bir tuş vuruşunun ardından bir değer dönüştürme gerçekleşir. Olayı bir -bound türüyle oninputhedeflerkenint, kullanıcının nokta (.) karakteri yazması engellenir. Nokta (.) karakteri hemen kaldırılır, bu nedenle kullanıcı yalnızca tam sayılara izin verilen hemen geri bildirim alır. Kullanıcının ayrıştırılamaz oninput bir değeri temizlemesine izin verilmesi gerektiği durumlar gibi olaydaki <input> değeri geri döndürmenin ideal olmadığı senaryolar vardır. Alternatifler şunlardır:
- Olayı kullanmayın
oninput. Öğe odağı kaybedene kadar geçersiz bir değerin geri döndürülmediği varsayılanonchangeolayı kullanın. - veya gibi
int?stringnull atanabilir bir türe bağlanıp değiştiricileri kullanın@bind:get/@bind:set(bu makalenin başlarında açıklanmıştır) veya geçersiz girişleri işlemek için özelgetveseterişimci mantığına sahip bir özelliğe bağlayın. - Form doğrulaması ile veya InputNumber<TValue>gibi InputDate<TValue> bir giriş bileşeni kullanın. Form doğrulama bileşenleriyle birlikte giriş bileşenleri, geçersiz girişleri yönetmek için yerleşik destek sağlar:
- Kullanıcının geçersiz giriş sağlamasına ve ilişkili EditContextüzerinde doğrulama hataları almasına izin ver.
- Kullanıcının ek web formu verileri girmesini engellemeden kullanıcı arabiriminde doğrulama hatalarını görüntüleyin.
Dizeleri biçimlendirme
Veri bağlama, kullanarak DateTimetek @bind:format="{FORMAT STRING}" biçimli bir dizeyle çalışır; burada {FORMAT STRING} yer tutucu, biçim dizesidir. Para birimi veya sayı biçimleri gibi diğer biçim ifadeleri şu anda kullanılamamaktadır, ancak gelecekteki bir sürüme eklenebilir.
DateBinding.razor:
@page "/date-binding"
<PageTitle>Date Binding</PageTitle>
<h1>Date Binding Example</h1>
<p>
<label>
<code>yyyy-MM-dd</code> format:
<input @bind="startDate" @bind:format="yyyy-MM-dd" />
</label>
</p>
<p>
<code>startDate</code>: @startDate
</p>
@code {
private DateTime startDate = new(2020, 1, 1);
}
@page "/date-binding"
<PageTitle>Date Binding</PageTitle>
<h1>Date Binding Example</h1>
<p>
<label>
<code>yyyy-MM-dd</code> format:
<input @bind="startDate" @bind:format="yyyy-MM-dd" />
</label>
</p>
<p>
<code>startDate</code>: @startDate
</p>
@code {
private DateTime startDate = new(2020, 1, 1);
}
@page "/date-binding"
<p>
<label>
<code>yyyy-MM-dd</code> format:
<input @bind="startDate" @bind:format="yyyy-MM-dd" />
</label>
</p>
<p>
<code>startDate</code>: @startDate
</p>
@code {
private DateTime startDate = new(2020, 1, 1);
}
@page "/date-binding"
<p>
<label>
<code>yyyy-MM-dd</code> format:
<input @bind="startDate" @bind:format="yyyy-MM-dd" />
</label>
</p>
<p>
<code>startDate</code>: @startDate
</p>
@code {
private DateTime startDate = new(2020, 1, 1);
}
@page "/date-binding"
<p>
<label>
<code>yyyy-MM-dd</code> format:
<input @bind="startDate" @bind:format="yyyy-MM-dd" />
</label>
</p>
<p>
<code>startDate</code>: @startDate
</p>
@code {
private DateTime startDate = new(2020, 1, 1);
}
@page "/date-binding"
<p>
<label>
<code>yyyy-MM-dd</code> format:
<input @bind="startDate" @bind:format="yyyy-MM-dd" />
</label>
</p>
<p>
<code>startDate</code>: @startDate
</p>
@code {
private DateTime startDate = new DateTime(2020, 1, 1);
}
Yukarıdaki kodda <input> , öğenin alan türü (type özniteliği) varsayılan olarak olur text.
Null atanabilir System.DateTime ve System.DateTimeOffset desteklenir:
private DateTime? date;
private DateTimeOffset? dateOffset;
Tarihleri biçimlendirmeye date yönelik yerleşik destek olduğundan, alan türü için bir biçim belirtilmesi Blazor önerilmez. Öneriye rağmen, yalnızca alan türüyle bir biçim sağlandığında bağlamanın yyyy-MM-dd düzgün çalışması için tarih biçimini kullanındate:
<input type="date" @bind="startDate" @bind:format="yyyy-MM-dd">
Bileşen parametreleriyle bağlama
Yaygın bir senaryo, bir alt bileşenin özelliğini üst bileşenindeki bir özelliğe bağlamaktır. Birden çok bağlama düzeyi aynı anda gerçekleştiğinden bu senaryo zincirleme bağlama olarak adlandırılır.
Bir alt bileşende söz dizimi ile @bind zincirlenmiş bağlamalar uygulayamazsınız. Üst öğedeki özelliğin alt bileşenden güncelleştirilmesini desteklemek için bir olay işleyicisi ve değeri ayrı olarak belirtilmelidir. Üst bileşen, alt bileşenle veri bağlamayı ayarlamak için söz dizimini kullanmaya devam eder @bind .
Aşağıdaki ChildBind bileşenin bir Year bileşen parametresi ve vardır EventCallback<TValue>. Kural gereği, EventCallback<TValue> parametresi için "Changed" soneki ile bileşen parametre adı olarak adlandırılmalıdır. Adlandırma söz dizimi, {PARAMETER NAME}Changedyer tutucunun {PARAMETER NAME} parametre adı olduğu şeklindedir. Aşağıdaki örnekte, EventCallback<TValue> olarak adlandırılmıştır YearChanged.
EventCallback.InvokeAsync sağlanan bağımsız değişkeniyle bağlamayla ilişkilendirilmiş temsilciyi çağırır ve değiştirilen özellik için bir olay bildirimi gönderilir.
ChildBind.razor:
<div class="card bg-light mt-3" style="width:18rem ">
<div class="card-body">
<h3 class="card-title">ChildBind Component</h3>
<p class="card-text">
Child <code>Year</code>: @Year
</p>
<button @onclick="UpdateYearFromChild">Update Year from Child</button>
</div>
</div>
@code {
[Parameter]
public int Year { get; set; }
[Parameter]
public EventCallback<int> YearChanged { get; set; }
private async Task UpdateYearFromChild() =>
await YearChanged.InvokeAsync(Random.Shared.Next(1950, 2021));
}
<div class="card bg-light mt-3" style="width:18rem ">
<div class="card-body">
<h3 class="card-title">ChildBind Component</h3>
<p class="card-text">
Child <code>Year</code>: @Year
</p>
<button @onclick="UpdateYearFromChild">Update Year from Child</button>
</div>
</div>
@code {
[Parameter]
public int Year { get; set; }
[Parameter]
public EventCallback<int> YearChanged { get; set; }
private async Task UpdateYearFromChild() =>
await YearChanged.InvokeAsync(Random.Shared.Next(1950, 2021));
}
<div class="card bg-light mt-3" style="width:18rem ">
<div class="card-body">
<h3 class="card-title">ChildBind Component</h3>
<p class="card-text">
Child <code>Year</code>: @Year
</p>
<button @onclick="UpdateYearFromChild">Update Year from Child</button>
</div>
</div>
@code {
[Parameter]
public int Year { get; set; }
[Parameter]
public EventCallback<int> YearChanged { get; set; }
private async Task UpdateYearFromChild()
{
await YearChanged.InvokeAsync(Random.Shared.Next(1950, 2021));
}
}
<div class="card bg-light mt-3" style="width:18rem ">
<div class="card-body">
<h3 class="card-title">ChildBind Component</h3>
<p class="card-text">
Child <code>Year</code>: @Year
</p>
<button @onclick="UpdateYearFromChild">Update Year from Child</button>
</div>
</div>
@code {
[Parameter]
public int Year { get; set; }
[Parameter]
public EventCallback<int> YearChanged { get; set; }
private async Task UpdateYearFromChild()
{
await YearChanged.InvokeAsync(Random.Shared.Next(1950, 2021));
}
}
<div class="card bg-light mt-3" style="width:18rem ">
<div class="card-body">
<h3 class="card-title">ChildBind Component</h3>
<p class="card-text">
Child <code>Year</code>: @Year
</p>
<button @onclick="UpdateYearFromChild">Update Year from Child</button>
</div>
</div>
@code {
private Random r = new();
[Parameter]
public int Year { get; set; }
[Parameter]
public EventCallback<int> YearChanged { get; set; }
private async Task UpdateYearFromChild()
{
await YearChanged.InvokeAsync(r.Next(1950, 2021));
}
}
<div class="card bg-light mt-3" style="width:18rem ">
<div class="card-body">
<h3 class="card-title">ChildBind Component</h3>
<p class="card-text">
Child <code>Year</code>: @Year
</p>
<button @onclick="UpdateYearFromChild">Update Year from Child</button>
</div>
</div>
@code {
private Random r = new Random();
[Parameter]
public int Year { get; set; }
[Parameter]
public EventCallback<int> YearChanged { get; set; }
private async Task UpdateYearFromChild()
{
await YearChanged.InvokeAsync(r.Next(1950, 2021));
}
}
ve EventCallback<TValue>olayları hakkında daha fazla bilgi için ASP.NET Core olay işlemeBlazorEventCallback bölümüne bakın.
Aşağıdaki Parent1 bileşende year , alan alt bileşenin Year parametresine bağlıdır.
Year parametresinin türüyle YearChanged eşleşen bir eşlikçi Year olayı olduğundan parametresi bağlanabilir.
Parent1.razor:
@page "/parent-1"
<PageTitle>Parent 1</PageTitle>
<h1>Parent Example 1</h1>
<p>Parent <code>year</code>: @year</p>
<button @onclick="UpdateYear">Update Parent <code>year</code></button>
<ChildBind @bind-Year="year" />
@code {
private int year = 1979;
private void UpdateYear() => year = Random.Shared.Next(1950, 2021);
}
@page "/parent-1"
<PageTitle>Parent 1</PageTitle>
<h1>Parent Example 1</h1>
<p>Parent <code>year</code>: @year</p>
<button @onclick="UpdateYear">Update Parent <code>year</code></button>
<ChildBind @bind-Year="year" />
@code {
private int year = 1979;
private void UpdateYear() => year = Random.Shared.Next(1950, 2021);
}
@page "/parent-1"
<h1>Parent Component</h1>
<p>Parent <code>year</code>: @year</p>
<button @onclick="UpdateYear">Update Parent <code>year</code></button>
<ChildBind @bind-Year="year" />
@code {
private int year = 1979;
private void UpdateYear()
{
year = Random.Shared.Next(1950, 2021);
}
}
@page "/parent-1"
<h1>Parent Component</h1>
<p>Parent <code>year</code>: @year</p>
<button @onclick="UpdateYear">Update Parent <code>year</code></button>
<ChildBind @bind-Year="year" />
@code {
private int year = 1979;
private void UpdateYear()
{
year = Random.Shared.Next(1950, 2021);
}
}
@page "/parent-1"
<h1>Parent Component</h1>
<p>Parent <code>year</code>: @year</p>
<button @onclick="UpdateYear">Update Parent <code>year</code></button>
<ChildBind @bind-Year="year" />
@code {
private Random r = new();
private int year = 1979;
private void UpdateYear()
{
year = r.Next(1950, 2021);
}
}
@page "/parent-1"
<h1>Parent Component</h1>
<p>Parent <code>year</code>: @year</p>
<button @onclick="UpdateYear">Update Parent <code>year</code></button>
<ChildBind @bind-Year="year" />
@code {
private Random r = new Random();
private int year = 1979;
private void UpdateYear()
{
year = r.Next(1950, 2021);
}
}
Bileşen parametresi bağlaması da olayları tetikleyebilir @bind:after . Aşağıdaki örnekte yöntemi, YearUpdated bileşen parametresini bağlamanın Year ardından zaman uyumsuz olarak yürütülür.
<ChildBind @bind-Year="year" @bind-Year:after="YearUpdated" />
@code {
...
private async Task YearUpdated()
{
... = await ...;
}
}
Kurala göre, bir özellik işleyiciye atanmış bir öznitelik ekleyerek ilgili olay @bind-{PROPERTY}:event işleyicisine bağlanabilir ve burada {PROPERTY} yer tutucu özelliğidir.
<ChildBind @bind-Year="year" /> yazmakla eşdeğerdir:
<ChildBind @bind-Year="year" @bind-Year:event="YearChanged" />
Daha karmaşık ve gerçek bir örnekte aşağıdaki PasswordEntry bileşen:
- Bir
<input>öğenin değerini birpasswordalana ayarlar. - Bir
Passwordözelliğin değişikliklerini, altEventCallbackalanın geçerli değerini bağımsız değişkeni olarak geçiren birpasswordüst bileşende kullanıma sunar. -
onclickyöntemini tetiklemekToggleShowPasswordiçin olayını kullanır. Daha fazla bilgi için bkz . ASP.NET Core Blazor olay işleme.
Uyarı
Uygulama gizli dizilerini, bağlantı dizesi'leri, kimlik bilgilerini, parolaları, kişisel kimlik numaralarını (PIN'ler), özel C#/.NET kodunu veya özel anahtarları/belirteçleri her zaman güvenli olmayan istemci tarafı kodunda depolamayın. Test/hazırlama ve üretim ortamlarında, sunucu tarafı Blazor kod ve web API'leri, proje kodu veya yapılandırma dosyalarında kimlik bilgilerinin korunmasını önleyen güvenli kimlik doğrulama akışları kullanmalıdır. Yerel geliştirme testlerinin dışında, ortam değişkenleri en güvenli yaklaşım olmadığından hassas verileri depolamak için ortam değişkenlerinin kullanılmasından kaçınmanızı öneririz. Yerel geliştirme testinde gizli verilerin güvenliğini sağlamak için Gizli Dizi Yöneticisi aracı önerilir. Daha fazla bilgi için bkz . Hassas verileri ve kimlik bilgilerini güvenli bir şekilde koruma.
PasswordEntry.razor:
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged" required type="password"
value="@password" />
</label>
</p>
</div>
</div>
@code {
private string? password;
[Parameter]
public string? Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private async Task OnPasswordChanged(ChangeEventArgs e)
{
password = e?.Value?.ToString();
await PasswordChanged.InvokeAsync(password);
}
}
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged" required type="password"
value="@password" />
</label>
</p>
</div>
</div>
@code {
private string? password;
[Parameter]
public string? Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private async Task OnPasswordChanged(ChangeEventArgs e)
{
password = e?.Value?.ToString();
await PasswordChanged.InvokeAsync(password);
}
}
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged" required type="password"
value="@password" />
</label>
</p>
</div>
</div>
@code {
private string? password;
[Parameter]
public string? Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private async Task OnPasswordChanged(ChangeEventArgs e)
{
password = e?.Value?.ToString();
await PasswordChanged.InvokeAsync(password);
}
}
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged" required type="password"
value="@password" />
</label>
</p>
</div>
</div>
@code {
private string? password;
[Parameter]
public string? Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private async Task OnPasswordChanged(ChangeEventArgs e)
{
password = e?.Value?.ToString();
await PasswordChanged.InvokeAsync(password);
}
}
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged" required type="password"
value="@password" />
</label>
</p>
</div>
</div>
@code {
private string password;
[Parameter]
public string Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private async Task OnPasswordChanged(ChangeEventArgs e)
{
password = e.Value.ToString();
await PasswordChanged.InvokeAsync(password);
}
}
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged" required type="password"
value="@password" />
</label>
</p>
</div>
</div>
@code {
private string password;
[Parameter]
public string Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private async Task OnPasswordChanged(ChangeEventArgs e)
{
password = e.Value.ToString();
await PasswordChanged.InvokeAsync(password);
}
}
Bileşen PasswordEntry , aşağıdaki PasswordBinding bileşen örneği gibi başka bir bileşende kullanılır.
PasswordBinding.razor:
@page "/password-binding"
<PageTitle>Password Binding</PageTitle>
<h1>Password Binding Example</h1>
<PasswordEntry @bind-Password="password" />
<p>
<code>password</code>: @password
</p>
@code {
private string password = "Not set";
}
@page "/password-binding"
<PageTitle>Password Binding</PageTitle>
<h1>Password Binding Example</h1>
<PasswordEntry @bind-Password="password" />
<p>
<code>password</code>: @password
</p>
@code {
private string password = "Not set";
}
@page "/password-binding"
<h1>Password Binding</h1>
<PasswordEntry @bind-Password="password" />
<p>
<code>password</code>: @password
</p>
@code {
private string password = "Not set";
}
@page "/password-binding"
<h1>Password Binding</h1>
<PasswordEntry @bind-Password="password" />
<p>
<code>password</code>: @password
</p>
@code {
private string password = "Not set";
}
@page "/password-binding"
<h1>Password Binding</h1>
<PasswordEntry @bind-Password="password" />
<p>
<code>password</code>: @password
</p>
@code {
private string password = "Not set";
}
@page "/password-binding"
<h1>Password Binding</h1>
<PasswordEntry @bind-Password="password" />
<p>
<code>password</code>: @password
</p>
@code {
private string password = "Not set";
}
PasswordBinding Bileşen başlangıçta işlendiğinde değeri passwordNot set kullanıcı arabiriminde görüntülenir. İlk işlemeden sonra değeri password , bileşendeki Password bileşen parametre değerinde PasswordEntry yapılan değişiklikleri yansıtır.
Not
Yukarıdaki örnek, parolayı alt PasswordEntry bileşenden üst PasswordBinding bileşene tek yönlü bağlar. Uygulamanın yalnızca parolayı üst öğeye geçiren uygulamanın çevresinde yeniden kullanmak üzere paylaşılan bir parola giriş bileşenine sahip olması bu senaryoda iki yönlü bağlama gereksinimi değildir. Doğrudan alt bileşenin parametresine yazmadan iki yönlü bağlamaya izin veren bir yaklaşım için, bu makalenin İkiden fazla bileşen arasında bağlama bölümündeki bileşen örneğine bakınNestedChild.
İşleyicide denetimler veya yakalama hataları gerçekleştirin. Aşağıdaki düzeltilmiş PasswordEntry bileşen, parolanın değerinde bir alan kullanılıyorsa kullanıcıya anında geri bildirim sağlar.
PasswordEntry.razor:
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged" required type="password"
value="@password" />
</label>
<span class="text-danger">@validationMessage</span>
</p>
</div>
</div>
@code {
private string? password;
private string? validationMessage;
[Parameter]
public string? Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private Task OnPasswordChanged(ChangeEventArgs e)
{
password = e?.Value?.ToString();
if (password != null && password.Contains(' '))
{
validationMessage = "Spaces not allowed!";
return Task.CompletedTask;
}
else
{
validationMessage = string.Empty;
return PasswordChanged.InvokeAsync(password);
}
}
}
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged" required type="password"
value="@password" />
</label>
<span class="text-danger">@validationMessage</span>
</p>
</div>
</div>
@code {
private string? password;
private string? validationMessage;
[Parameter]
public string? Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private Task OnPasswordChanged(ChangeEventArgs e)
{
password = e?.Value?.ToString();
if (password != null && password.Contains(' '))
{
validationMessage = "Spaces not allowed!";
return Task.CompletedTask;
}
else
{
validationMessage = string.Empty;
return PasswordChanged.InvokeAsync(password);
}
}
}
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged" required type="password"
value="@password" />
</label>
<span class="text-danger">@validationMessage</span>
</p>
</div>
</div>
@code {
private string? password;
private string? validationMessage;
[Parameter]
public string? Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private Task OnPasswordChanged(ChangeEventArgs e)
{
password = e?.Value?.ToString();
if (password != null && password.Contains(' '))
{
validationMessage = "Spaces not allowed!";
return Task.CompletedTask;
}
else
{
validationMessage = string.Empty;
return PasswordChanged.InvokeAsync(password);
}
}
}
Aşağıdaki örnekte yöntemi, PasswordUpdated bileşen parametresini bağlamanın Password ardından zaman uyumsuz olarak yürütülür:
<PasswordEntry @bind-Password="password" @bind-Password:after="PasswordUpdated" />
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged" required type="password"
value="@password" />
</label>
<span class="text-danger">@validationMessage</span>
</p>
</div>
</div>
@code {
private string? password;
private string? validationMessage;
[Parameter]
public string? Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private Task OnPasswordChanged(ChangeEventArgs e)
{
password = e?.Value?.ToString();
if (password != null && password.Contains(' '))
{
validationMessage = "Spaces not allowed!";
return Task.CompletedTask;
}
else
{
validationMessage = string.Empty;
return PasswordChanged.InvokeAsync(password);
}
}
}
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged" required type="password"
value="@password" />
</label>
<span class="text-danger">@validationMessage</span>
</p>
</div>
</div>
@code {
private string password;
private string validationMessage;
[Parameter]
public string Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private Task OnPasswordChanged(ChangeEventArgs e)
{
password = e.Value.ToString();
if (password.Contains(' '))
{
validationMessage = "Spaces not allowed!";
return Task.CompletedTask;
}
else
{
validationMessage = string.Empty;
return PasswordChanged.InvokeAsync(password);
}
}
}
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged" required type="password"
value="@password" />
</label>
<span class="text-danger">@validationMessage</span>
</p>
</div>
</div>
@code {
private string password;
private string validationMessage;
[Parameter]
public string Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private Task OnPasswordChanged(ChangeEventArgs e)
{
password = e.Value.ToString();
if (password.Contains(' '))
{
validationMessage = "Spaces not allowed!";
return Task.CompletedTask;
}
else
{
validationMessage = string.Empty;
return PasswordChanged.InvokeAsync(password);
}
}
}
İkiden fazla bileşen arasında bağlama
parametreleri istediğiniz sayıda iç içe bileşen aracılığıyla bağlayabilirsiniz, ancak tek yönlü veri akışına saygı göstermelisiniz:
- Değişiklik bildirimleri hiyerarşiyi yukarı taşır.
- Yeni parametre değerleri hiyerarşide aşağı doğru akar.
Yaygın ve önerilen bir yaklaşım, aşağıdaki örnekte gösterildiği gibi hangi durumun güncelleştirilmesi gerektiği konusunda herhangi bir karışıklığı önlemek için yalnızca temel alınan verileri üst bileşende depolamaktır.
Parent2.razor:
@page "/parent-2"
<PageTitle>Parent 2</PageTitle>
<h1>Parent Example 2</h1>
<p>Parent Message: <b>@parentMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Parent</button>
</p>
<NestedChild @bind-ChildMessage="parentMessage" />
@code {
private string parentMessage = "Initial value set in Parent";
private void ChangeValue() => parentMessage = $"Set in Parent {DateTime.Now}";
}
@page "/parent-2"
<PageTitle>Parent 2</PageTitle>
<h1>Parent Example 2</h1>
<p>Parent Message: <b>@parentMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Parent</button>
</p>
<NestedChild @bind-ChildMessage="parentMessage" />
@code {
private string parentMessage = "Initial value set in Parent";
private void ChangeValue() => parentMessage = $"Set in Parent {DateTime.Now}";
}
@page "/parent-2"
<h1>Parent Component</h1>
<p>Parent Message: <b>@parentMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Parent</button>
</p>
<NestedChild @bind-ChildMessage="parentMessage" />
@code {
private string parentMessage = "Initial value set in Parent";
private void ChangeValue()
{
parentMessage = $"Set in Parent {DateTime.Now}";
}
}
@page "/parent-2"
<h1>Parent Component</h1>
<p>Parent Message: <b>@parentMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Parent</button>
</p>
<NestedChild @bind-ChildMessage="parentMessage" />
@code {
private string parentMessage = "Initial value set in Parent";
private void ChangeValue()
{
parentMessage = $"Set in Parent {DateTime.Now}";
}
}
@page "/parent-2"
<h1>Parent Component</h1>
<p>Parent Message: <b>@parentMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Parent</button>
</p>
<NestedChild @bind-ChildMessage="parentMessage" />
@code {
private string parentMessage = "Initial value set in Parent";
private void ChangeValue()
{
parentMessage = $"Set in Parent {DateTime.Now}";
}
}
@page "/parent-2"
<h1>Parent Component</h1>
<p>Parent Message: <b>@parentMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Parent</button>
</p>
<NestedChild @bind-ChildMessage="parentMessage" />
@code {
private string parentMessage = "Initial value set in Parent";
private void ChangeValue()
{
parentMessage = $"Set in Parent {DateTime.Now}";
}
}
Aşağıdaki NestedChild bileşende NestedGrandchild , bileşen:
- değerini
ChildMessageGrandchildMessagesöz dizimi ile@bind:getatar. - Söz dizimi ile
GrandchildMessageyürütülürkenChildMessageChangedgüncelleştirmeler@bind:set.
.NET 7'nin yayımlanmasından önce, bileşenler arasında iki yönlü bağlama, bir ayarlayıcısında get tarafından döndürülen /'ü atan üçüncü bir özellik ile birlikte setTaskEventCallback.InvokeAsync erişimcilerini kullanır.
Bir bileşen parametresinin değerini doğrudan değiştirmekten kaçınmanın nedeni, alt bileşenin üst bileşenin durumunu etkili bir şekilde değiştirmesidir. Bu, Blazor'nin değişiklik algılama sürecini etkileyebilir ve parametreler giriş olarak kullanılmak üzere tasarlandıkları için, bunların değişken bir durum olmaması gerektiğinden ekstra işleme döngülerini tetikleyebilir. Verilerin bileşenler arasında geçirildiği zincirlenmiş senaryolarda, bir bileşen parametresine doğrudan yazmak, uygulamayı kilitleyen sonsuz rerender'lar gibi istenmeyen etkilere yol açabilir.
@bind:get
/
@bind:set söz dizimi şunları yapmanızı sağlar:
- .NET 7'nin yayımlanmasından önce gerekli olan zincirlenmiş bileşenler arasında yalnızca değerleri ve geri çağırmaları iletmek için var olan ek bir özellik oluşturmaktan kaçının.
- Değerleri uygulanmadan önce yakala ve dönüştür.
- İki yönlü bağlamayı desteklerken parametreyi alt öğede değişmez tutun.
Yararlı bir benzetme, HTML'nin <input> aşağıdaki değer durumlarını izleyen öğesidir:
-
defaultValue: Ebeveynden alınan bir bileşen parametresi gibi. -
value: Bileşenin içindeki mevcut durum gibi.
Eğer defaultValue doğrudan değiştirirseniz, sözleşmeyi bozuyorsunuz. Bunun yerine, bu durumlar ayrı tutulur ve öğenin ilk işlenmesinden sonra yalnızca value, kontrol edilen yöntemler aracılığıyla güncelleştirilir. Aynı mantık bileşen parametreleri için de geçerlidir ve söz diziminin kullanılması @bind:get/@bind:set , doğrudan bileşen parametrelerine yazmayla ilişkili istenmeyen işleme efektlerini önler.
NestedChild.razor:
<div class="border rounded m-1 p-1">
<h2>Child Component</h2>
<p>Child Message: <b>@ChildMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Child</button>
</p>
<NestedGrandchild @bind-GrandchildMessage:get="ChildMessage"
@bind-GrandchildMessage:set="ChildMessageChanged" />
</div>
@code {
[Parameter]
public string? ChildMessage { get; set; }
[Parameter]
public EventCallback<string?> ChildMessageChanged { get; set; }
private async Task ChangeValue() =>
await ChildMessageChanged.InvokeAsync($"Set in Child {DateTime.Now}");
}
<div class="border rounded m-1 p-1">
<h2>Child Component</h2>
<p>Child Message: <b>@ChildMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Child</button>
</p>
<NestedGrandchild @bind-GrandchildMessage:get="ChildMessage"
@bind-GrandchildMessage:set="ChildMessageChanged" />
</div>
@code {
[Parameter]
public string? ChildMessage { get; set; }
[Parameter]
public EventCallback<string?> ChildMessageChanged { get; set; }
private async Task ChangeValue() =>
await ChildMessageChanged.InvokeAsync($"Set in Child {DateTime.Now}");
}
<div class="border rounded m-1 p-1">
<h2>Child Component</h2>
<p>Child Message: <b>@ChildMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Child</button>
</p>
<NestedGrandchild @bind-GrandchildMessage:get="ChildMessage"
@bind-GrandchildMessage:set="ChildMessageChanged" />
</div>
@code {
[Parameter]
public string? ChildMessage { get; set; }
[Parameter]
public EventCallback<string?> ChildMessageChanged { get; set; }
private async Task ChangeValue()
{
await ChildMessageChanged.InvokeAsync(
$"Set in Child {DateTime.Now}");
}
}
<div class="border rounded m-1 p-1">
<h2>Child Component</h2>
<p>Child Message: <b>@ChildMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Child</button>
</p>
<NestedGrandchild @bind-GrandchildMessage="BoundValue" />
</div>
@code {
[Parameter]
public string? ChildMessage { get; set; }
[Parameter]
public EventCallback<string> ChildMessageChanged { get; set; }
private string BoundValue
{
get => ChildMessage ?? string.Empty;
set => ChildMessageChanged.InvokeAsync(value);
}
private async Task ChangeValue()
{
await ChildMessageChanged.InvokeAsync(
$"Set in Child {DateTime.Now}");
}
}
<div class="border rounded m-1 p-1">
<h2>Child Component</h2>
<p>Child Message: <b>@ChildMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Child</button>
</p>
<NestedGrandchild @bind-GrandchildMessage="BoundValue" />
</div>
@code {
[Parameter]
public string ChildMessage { get; set; }
[Parameter]
public EventCallback<string> ChildMessageChanged { get; set; }
private string BoundValue
{
get => ChildMessage;
set => ChildMessageChanged.InvokeAsync(value);
}
private async Task ChangeValue()
{
await ChildMessageChanged.InvokeAsync(
$"Set in Child {DateTime.Now}");
}
}
<div class="border rounded m-1 p-1">
<h2>Child Component</h2>
<p>Child Message: <b>@ChildMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Child</button>
</p>
<NestedGrandchild @bind-GrandchildMessage="BoundValue" />
</div>
@code {
[Parameter]
public string ChildMessage { get; set; }
[Parameter]
public EventCallback<string> ChildMessageChanged { get; set; }
private string BoundValue
{
get => ChildMessage;
set => ChildMessageChanged.InvokeAsync(value);
}
private async Task ChangeValue()
{
await ChildMessageChanged.InvokeAsync(
$"Set in Child {DateTime.Now}");
}
}
Uyarı
Genel olarak, doğrudan kendi bileşen parametrelerine yazan bileşenler oluşturmaktan kaçının. Önceki NestedChild bileşen, doğrudan BoundValue parametresine yazmak yerine bir ChildMessage özelliği kullanır. Daha fazla bilgi için bkz . ASP.NET Core'da Blazorparametrelerin üzerine yazmaktan kaçının.
NestedGrandchild.razor:
<div class="border rounded m-1 p-1">
<h3>Grandchild Component</h3>
<p>Grandchild Message: <b>@GrandchildMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Grandchild</button>
</p>
</div>
@code {
[Parameter]
public string? GrandchildMessage { get; set; }
[Parameter]
public EventCallback<string> GrandchildMessageChanged { get; set; }
private async Task ChangeValue() =>
await GrandchildMessageChanged.InvokeAsync(
$"Set in Grandchild {DateTime.Now}");
}
<div class="border rounded m-1 p-1">
<h3>Grandchild Component</h3>
<p>Grandchild Message: <b>@GrandchildMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Grandchild</button>
</p>
</div>
@code {
[Parameter]
public string? GrandchildMessage { get; set; }
[Parameter]
public EventCallback<string> GrandchildMessageChanged { get; set; }
private async Task ChangeValue() =>
await GrandchildMessageChanged.InvokeAsync(
$"Set in Grandchild {DateTime.Now}");
}
<div class="border rounded m-1 p-1">
<h3>Grandchild Component</h3>
<p>Grandchild Message: <b>@GrandchildMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Grandchild</button>
</p>
</div>
@code {
[Parameter]
public string? GrandchildMessage { get; set; }
[Parameter]
public EventCallback<string> GrandchildMessageChanged { get; set; }
private async Task ChangeValue()
{
await GrandchildMessageChanged.InvokeAsync(
$"Set in Grandchild {DateTime.Now}");
}
}
<div class="border rounded m-1 p-1">
<h3>Grandchild Component</h3>
<p>Grandchild Message: <b>@GrandchildMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Grandchild</button>
</p>
</div>
@code {
[Parameter]
public string? GrandchildMessage { get; set; }
[Parameter]
public EventCallback<string> GrandchildMessageChanged { get; set; }
private async Task ChangeValue()
{
await GrandchildMessageChanged.InvokeAsync(
$"Set in Grandchild {DateTime.Now}");
}
}
<div class="border rounded m-1 p-1">
<h3>Grandchild Component</h3>
<p>Grandchild Message: <b>@GrandchildMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Grandchild</button>
</p>
</div>
@code {
[Parameter]
public string GrandchildMessage { get; set; }
[Parameter]
public EventCallback<string> GrandchildMessageChanged { get; set; }
private async Task ChangeValue()
{
await GrandchildMessageChanged.InvokeAsync(
$"Set in Grandchild {DateTime.Now}");
}
}
<div class="border rounded m-1 p-1">
<h3>Grandchild Component</h3>
<p>Grandchild Message: <b>@GrandchildMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Grandchild</button>
</p>
</div>
@code {
[Parameter]
public string GrandchildMessage { get; set; }
[Parameter]
public EventCallback<string> GrandchildMessageChanged { get; set; }
private async Task ChangeValue()
{
await GrandchildMessageChanged.InvokeAsync(
$"Set in Grandchild {DateTime.Now}");
}
}
Bellekte ve iç içe olması gerekmeyen bileşenler arasında veri paylaşmaya uygun alternatif bir yaklaşım için bkz . ASP.NET Çekirdek Blazor durum yönetimine genel bakış.
İlişkili alan veya özellik ifade ağacı
Bağlamayla daha derin etkileşimleri kolaylaştırmak için, Blazor ilişkili bir alanın veya özelliğin ifade ağacını yakalamanıza olanak tanır. Bu, ile son ekli alan veya özellik adı ile bir özellik tanımlanarak elde edilir Expression. adlı {FIELD OR PROPERTY NAME}herhangi bir alan veya özellik için karşılık gelen ifade ağacı özelliği olarak adlandırılır {FIELD OR PROPERTY NAME}Expression.
Aşağıdaki ChildParameterExpression bileşen, ifadenin Year modelini ve alan adını tanımlar.
FieldIdentifierModel ve alan adını almak için kullanılan bir , düzenlenebilen tek bir alanı benzersiz olarak tanımlar. Bu, model nesnesinde bir özelliğe karşılık gelebilir veya başka bir adlandırılmış değer olabilir. Bir parametrenin ifadesinin kullanılması, Microsoft Blazor belgelerinde yer almayan ancak çok sayıda üçüncü taraf kaynağı tarafından ele alınan özel doğrulama bileşenleri oluştururken kullanışlıdır.
ChildParameterExpression.razor:
@using System.Linq.Expressions
<ul>
<li>Year model: @yearField.Model</li>
<li>Year field name: @yearField.FieldName</li>
</ul>
@code {
private FieldIdentifier yearField;
[Parameter]
public int Year { get; set; }
[Parameter]
public EventCallback<int> YearChanged { get; set; }
[Parameter]
public Expression<Func<int>> YearExpression { get; set; } = default!;
protected override void OnInitialized() =>
yearField = FieldIdentifier.Create(YearExpression);
}
@using System.Linq.Expressions
<ul>
<li>Year model: @yearField.Model</li>
<li>Year field name: @yearField.FieldName</li>
</ul>
@code {
private FieldIdentifier yearField;
[Parameter]
public int Year { get; set; }
[Parameter]
public EventCallback<int> YearChanged { get; set; }
[Parameter]
public Expression<Func<int>> YearExpression { get; set; } = default!;
protected override void OnInitialized() =>
yearField = FieldIdentifier.Create(YearExpression);
}
@using System.Linq.Expressions
<ul>
<li>Year model: @yearField.Model</li>
<li>Year field name: @yearField.FieldName</li>
</ul>
@code {
private FieldIdentifier yearField;
[Parameter]
public int Year { get; set; }
[Parameter]
public EventCallback<int> YearChanged { get; set; }
[Parameter]
public Expression<Func<int>> YearExpression { get; set; } = default!;
protected override void OnInitialized()
{
yearField = FieldIdentifier.Create(YearExpression);
}
}
@using System.Linq.Expressions
<ul>
<li>Year model: @yearField.Model</li>
<li>Year field name: @yearField.FieldName</li>
</ul>
@code {
private FieldIdentifier yearField;
[Parameter]
public int Year { get; set; }
[Parameter]
public EventCallback<int> YearChanged { get; set; }
[Parameter]
public Expression<Func<int>> YearExpression { get; set; } = default!;
protected override void OnInitialized()
{
yearField = FieldIdentifier.Create(YearExpression);
}
}
@using System.Linq.Expressions
<ul>
<li>Year model: @yearField.Model</li>
<li>Year field name: @yearField.FieldName</li>
</ul>
@code {
private FieldIdentifier yearField;
[Parameter]
public int Year { get; set; }
[Parameter]
public EventCallback<int> YearChanged { get; set; }
[Parameter]
public Expression<Func<int>> YearExpression { get; set; } = default!;
protected override void OnInitialized()
{
yearField = FieldIdentifier.Create(YearExpression);
}
}
@using System.Linq.Expressions
<ul>
<li>Year model: @yearField.Model</li>
<li>Year field name: @yearField.FieldName</li>
</ul>
@code {
private FieldIdentifier yearField;
[Parameter]
public int Year { get; set; }
[Parameter]
public EventCallback<int> YearChanged { get; set; }
[Parameter]
public Expression<Func<int>> YearExpression { get; set; } = default!;
protected override void OnInitialized()
{
yearField = FieldIdentifier.Create(YearExpression);
}
}
Parent3.razor:
@page "/parent-3"
<PageTitle>Parent 3</PageTitle>
<h1>Parent Example 3</h1>
<p>Parent <code>year</code>: @year</p>
<ChildParameterExpression @bind-Year="year" />
@code {
private int year = 1979;
}
@page "/parent-3"
<PageTitle>Parent 3</PageTitle>
<h1>Parent Example 3</h1>
<p>Parent <code>year</code>: @year</p>
<ChildParameterExpression @bind-Year="year" />
@code {
private int year = 1979;
}
@page "/parent-3"
<h1>Parent Example 3</h1>
<p>Parent <code>year</code>: @year</p>
<ChildParameterExpression @bind-Year="year" />
@code {
private int year = 1979;
}
@page "/parent-3"
<h1>Parent Example 3</h1>
<p>Parent <code>year</code>: @year</p>
<ChildParameterExpression @bind-Year="year" />
@code {
private int year = 1979;
}
@page "/parent-3"
<h1>Parent Example 3</h1>
<p>Parent <code>year</code>: @year</p>
<ChildParameterExpression @bind-Year="year" />
@code {
private int year = 1979;
}
@page "/parent-3"
<h1>Parent Example 3</h1>
<p>Parent <code>year</code>: @year</p>
<ChildParameterExpression @bind-Year="year" />
@code {
private int year = 1979;
}
Ek kaynaklar
- Parametre değişikliği algılama ve bileşen işleme hakkında Razor ek yönergeler
- ASP.NET Core Blazor formlara genel bakış
- Formdaki radyo düğmelerine bağlama
-
C# nesne
InputSelectdeğerlerine bağlamanullseçenekleri -
ASP.NET Çekirdek Blazor olay işleme:
EventCallbackbölüm -
Blazor (
dotnet/blazor-samplesnasıl indirilir)
ASP.NET Core