BlazorASP.NET Core veri bağlama

Razor bileşenleri bir alan, özellik veya @bind Razor ifade değeri ile yönerge özniteliğiyle veri bağlama Razor özellikleri sağlar.

Aşağıdaki örnek bağlar:

  • <input>C# alanına bir öğe inputValue değeri.
  • <input>C# özelliğine ikinci bir öğe InputValue değeri.

Bir öğe <input> odağı kaybettiğinde, bağımlı alanı veya özelliği güncelleştirilir.

Pages/Bind.razor:

@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şlendiklerde 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 kendi kendini işledikten sonra, alan ve özellik güncelleştirmeleri genellikle bir olay işleyicisi tetiklendiğinde kullanıcı arabirimine yansıtılacaktır.

Aşağıdaki örnek, veri bağlamanın HTML'de nasıl oluşturacağının bir gösterimi olarak özelliğini InputValue ikinci <input> öğenin ve value onchange özniteliklerine bağlar. Aşağıdaki örnekteki ikinci öğe bir kavram gösterimidir ve bileşenlerdeki verileri <input> bağlamayı önermek için Razor değildir.

Pages/BindTheory.razor:

@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; }
}

Bileşen BindTheory işlenecek value olduğunda, HTML tanıtım <input> öğesinin InputValue özelliğinden gelir. Kullanıcı metin kutusuna bir değer girin ve öğe odağında değişiklik yapın, olay başlatıldı ve onchange InputValue özelliği değiştirilen değere ayarlanır. Gerçekte kod yürütme daha karmaşıktır çünkü @bind tür dönüştürmeleri gerçekleştirilen örnekleri işler. Genel olarak, @bind bir ifadenin geçerli değerini bir öznitelikle value ilişkilendirin ve kayıtlı işleyiciyi kullanarak değişiklikleri işler.

Bir özelliği veya alanı diğer Belge Nesne Modeli (DOM) olaylarını, yer tutucu için @bind:event="{EVENT}" DOM olayına sahip bir özniteliği dahil edecek şekilde {EVENT} bağlayın. Aşağıdaki örnek, InputValue öğenin olayı <input> tetiklendiğinde özelliğini öğenin oninput değerine bağlar. Öğe onchange odağıkaybettiğinde çıkan olayın aksine, oninput metin kutusunun değeri değiştiğında etkindir.

Page/BindEvent.razor:

@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ğlaması büyük/büyük/büyük harfe duyarlıdır:

  • @bind ve @bind:event geçerlidir.
  • @Bind/@Bind:Event(büyük harfler B E ve ) veya @BIND / @BIND:EVENT (tüm büyük harfler) geçersizdir.

Öğelerle birden çok seçenek <input> seçimi

Bağlama, multiple öğelerle seçenek seçimini <input> destekler. olayı, @onchange seçilen öğelerin bir dizisini olay bağımsız değişkenleri ( ) aracılığıyla ChangeEventArgs sağlar. Değerin bir dizi türüne bağlı olması gerekir.

Pages/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; } = new string[] { };
    public string[] SelectedCities { get; set; } = new[] { "bal", "sea" };

    void SelectedCarsChanged(ChangeEventArgs e)
    {
        SelectedCars = (string[])e.Value;
    }
}

Boş dizelerin ve değerlerin veri bağlamada nasıl işlen olduğu hakkında bilgi için C# nesne değerlerine öğe null seçeneklerini bağlama <select> null bölümüne bakın.

Öğe <select> seçeneklerini C# nesne değerlerine null bağlama

Bir öğe seçeneği değerini C# nesne değeri olarak <select> temsil etmek için mantıklı bir yol null yoktur, çünkü:

  • HTML özniteliklerinin değerleri null olabilir. HTML'de null değerine en yakın olan öğedeki HTML value <option> özniteliğinin olmamasıdır.
  • Özniteliğiz <option> bir value öğesinin seçiminde tarayıcı, değeri bu öğenin metin içeriği olarak <option> davranır.

Çerçeve, Blazor aşağıdakiler dahil olduğundan varsayılan davranışı gizlemeye çalışmaz:

  • Çerçevede özel durum geçici çözümleri zinciri oluşturma.
  • Geçerli çerçeve davranışında yeni değişiklikler.

HTML'de en makul null eşdeğer boş bir dizedir. value Çerçeve, bir değerine iki yol içeren bağlama için boş dize Blazor null <select> dönüştürmelerini işler.

Ayrılamaz değerler

Kullanıcı veriye bağlı öğeye ayrılamaz bir değer sağladığında, bağlama olayı tetiklendiğinde, ayrılamaz değer otomatik olarak önceki değerine geri döner.

Bir öğenin başlangıç değerine <input> sahip bir türe bağlı int olduğu aşağıdaki bileşeni göz önünde bulundurarak. 123

Pages/UnparsableValues.razor:

@page "/unparseable-values"

<p>
    <input @bind="inputValue" />
</p>

<p>
    <code>inputValue</code>: @inputValue
</p>

@code {
    private int inputValue = 123;
}

Bağlama varsayılan olarak öğenin olayına onchange uygulanır. Kullanıcı metin kutusunun girişinin değerini olarak değiştirirse ve odağı değiştirirse, öğenin değeri, ne zaman 123.45 123 başlatıldığında onchange değerine geri döner. değeri 123.45 özgün değerine göre reddedilirse 123 kullanıcı, değerinin kabul edilme olmadığını anlar.

olayı oninput için ( ), bir değer geri çevirmesi, ayrılamaz bir değere neden olan herhangi bir @bind:event="oninput" tuş vuruşu sonrasında gerçekleşir. Bir -bound oninput türü ile olayı int hedeflerken, kullanıcının nokta ( ) karakteri . yazması engellenebilir. Nokta ( ) karakteri hemen kaldırılır, bu nedenle kullanıcı yalnızca tam . sayılara izin verildiğini hemen geri alır. Olayda değerin geri döndürülme ideal bir senaryo değildir, örneğin kullanıcının ayrılamaz bir değeri temizlemesine izin ver oninput gerektiği <input> senaryolar vardır. Alternatifler şunlardır:

  • Olayı oninput kullanma. Öğe odağı onchange kaybedilinceye kadar geçersiz bir değerin geri döndürül almay olduğu varsayılan olayı kullanın.
  • veya gibi null değere sahip bir türe int? bağlayın ve geçersiz girişleri işlemek için string get set özel ve erişimci mantığı sağlar.
  • veya gibi bir form doğrulamabileşeni InputNumber<TValue> InputDate<TValue> kullanın. Form doğrulama bileşenleri, geçersiz girişleri yönetmek için yerleşik destek sağlar. Form doğrulama bileşenleri:
    • Kullanıcıya geçersiz giriş sağlama ve ilişkili üzerinde doğrulama hataları alma izni EditContext verme.
    • Kullanıcının ek webform verileri girmesini engellemeden kullanıcı arabiriminde doğrulama hatalarını görüntüleme.

Biçim dizeleri

Veri bağlama, kullanarak tek DateTime biçimli bir dizeyle @bind:format="{FORMAT STRING}" ç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ılamaz, ancak gelecekteki bir sürümde eklenebilir.

Pages/DateBinding.razor:

@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);
}

Yukarıdaki kodda, <input> öğesinin alan türü ( type özniteliği) varsayılan olarak text kullanılır.

Null System.DateTime değere sahip System.DateTimeOffset olabilir ve şu destekleri destekler:

private DateTime? date;
private DateTimeOffset? dateOffset;

Tarih biçimlendirmek için yerleşik destek olduğundan, alan date türü için bir biçim Blazor belirterek önerilmez. Öneriye rağmen, bağlamanın doğru çalışması için tarih biçimini yalnızca alan türüyle birlikte bir biçim yyyy-MM-dd date sağlanmalıdır:

<input type="date" @bind="startDate" @bind:format="yyyy-MM-dd">

Özel bağlama biçimleri

C# get set ve erişimcileri, aşağıdaki bileşende de olduğu gibi özel bağlama biçimi davranışı DecimalBinding oluşturmak için kullanılabilir. Bileşen, bir özelliği ( ) ile bir öğeye en fazla üç ondalık basamağa sahip pozitif <input> veya negatif bir ondalık basamak string DecimalValue bağlar.

Pages/DecimalBinding.razor:

@page "/decimal-binding"
@using System.Globalization

<p>
    <label>
        Decimal value (&plusmn;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);
            }
        }
    }
}

Bileşen parametreleriyle bağlama

Yaygın bir senaryo, bir alt bileşenin özelliğini üst bileşeninde bir özele bağlamadır. Birden çok bağlama düzeyi aynı anda oluştuğu için bu senaryoya zincirleme bağlama adı verilmektedir.

Bileşen parametreleri, bir üst bileşenin özelliklerini söz dizimi ile bağlamaya izin @bind-{PROPERTY} verir; burada {PROPERTY} yer tutucu, bağlanılacağı özelliktir.

Alt bileşende söz dizimi ile @bind zincirleme bağlamalar uygulayayız. Üst öğede özelliğin alt bileşenden güncelleştirilsini desteklemek için bir olay işleyicisi ve değeri ayrı ayrı belirtilmelidir.

Üst bileşen, alt @bind bileşenle veri bağlamayı ayarlamak için söz dizimlerini kullanır.

Aşağıdaki ChildBind bileşenin bir bileşen Year parametresi ve bir EventCallback<TValue> vardır. Kural gereği, parametresinin bileşen parametre adı olarak " " soneki EventCallback<TValue> Changed ile adlandırılmış olması gerekir. Adlandırma söz dizimi {PARAMETER NAME}Changed değeridir; burada {PARAMETER NAME} yer tutucu parametre adıdır. Aşağıdaki örnekte, olarak EventCallback<TValue> adlandırılmış. YearChanged

EventCallback.InvokeAsync , sağlanan bağımsız değişkeniyle bağlamayla ilişkili temsilciyi çağırır ve değiştirilen özellik için bir olay bildirimi göndermektedir.

Shared/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 {
    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));
    }
}

ve olayları hakkında daha fazla bilgi EventCallback<TValue> için makalenin EventCallback bölümüne ASP.NET Core Blazor olay işleme bakın.

Aşağıdaki Parent bileşende, year alanı alt Year bileşenin parametresine bağlıdır. parametresi, Year parametrenin türüyle eşleşen bir YearChanged yardımcı olaya sahip olduğundan Year bağlanabilir.

Pages/Parent.razor:

@page "/Parent"

<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);
    }
}

Kural gereği, bir özellik, yer tutucu özelliği olduğu işleyiciye atanmış bir öznitelik dahil tarafından karşılık @bind-{PROPERTY}:event gelen olay {PROPERTY} işleyiciye bağlanabilir. <ChildBind @bind-Year="year" /> yazmakla eşdeğerdir:

<ChildBind @bind-Year="year" @bind-Year:event="YearChanged" />

Daha karmaşık ve gerçek dünya örneğinde aşağıdaki PasswordEntry bileşen:

  • Öğenin <input> değerini bir alana password ayarlar.
  • Bir özelliğin değişikliklerini, alt alanın geçerli değerinde bağımsız değişken olarak geçen bir Password EventCallback üst password bileşene gösterir.
  • yöntemini onclick tetiklemek için olayı ToggleShowPassword kullanır. Daha fazla bilgi için bkz. ASP.NET Core Blazor olay işleme.

Shared/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="@(showPassword ? "text" : "password")"
                       value="@password" />
            </label>
        </p>
        <button class="btn btn-primary" @onclick="ToggleShowPassword">
            Show password
        </button>
    </div>
</div>

@code {
    private bool showPassword;
    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);
    }

    private void ToggleShowPassword()
    {
        showPassword = !showPassword;
    }
}

Bileşen, PasswordEntry aşağıdaki bileşen örneği gibi başka bir PasswordBinding bileşende kullanılır.

Pages/PasswordBinding.razor:

@page "/password-binding"

<h1>Password Binding</h1>

<PasswordEntry @bind-Password="password" />

<p>
    <code>password</code>: @password
</p>

@code {
    private string password = "Not set";
}

Bileşen PasswordBinding başlangıçta işlendiğinde değeri password kullanıcı Not set arabiriminde görüntülenir. İlk işlemeden sonra password değeri, bileşende bileşen parametre Password değerinde yapılan değişiklikleri PasswordEntry gösterir.

Not

Yukarıdaki örnek, parolayı alt bileşenden üst PasswordEntry bileşene tek bir yolla PasswordBinding bağlar. Hedef, uygulamanın yalnızca üst öğeye geçen uygulamanın etrafında yeniden kullanmak üzere paylaşılan bir parola giriş bileşenine sahip olması ise, bu senaryoda iki yollü bağlama gerekli değildir. Doğrudan alt bileşenin parametresine yazmadan iki yol bağlamaya izin verme yaklaşımı için,bu makalenin İkiden fazla bileşen arasında bağlama bölümündeki NestedChild bileşen örneğine bakın.

İşleyicide denetimler veya yakalama hataları gerçekleştirin. Aşağıdaki düzeltilmiş PasswordEntry bileşen, parola değerinde bir alan kullanılıyorsa kullanıcıya anında geri bildirim sağlar.

Shared/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="@(showPassword ? "text" : "password")"
                       value="@password" />
            </label>
            <span class="text-danger">@validationMessage</span>
        </p>
        <button class="btn btn-primary" @onclick="ToggleShowPassword">
            Show password
        </button>
    </div>
</div>

@code {
    private bool showPassword;
    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);
        }
    }

    private void ToggleShowPassword()
    {
        showPassword = !showPassword;
    }
}

İkiden fazla bileşen arasında bağlama

Parametreleri herhangi bir sayıda iç içe bileşen aracılığıyla b bağlamanız gerekir, ancak tek yol veri akışına saygı gösterebilirsiniz:

  • Değişiklik bildirimleri hiyerarşisinde yukarı doğru akar.
  • Yeni parametre değerleri hiyerarşisinde aşağı doğru akar.

Ortak ve önerilen bir yaklaşım, aşağıdaki örnekte gösterildiği gibi, hangi durumun güncellenmesi gerektiği hakkında karışıklık oluşmasını önlemek için yalnızca ana bileşende temel alınan verileri saklamaktır.

Pages/Parent.razor:

@page "/parent"

<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}";
    }
}

Shared/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="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}");
    }
}

Uyarı

Genellikle, kendi bileşen parametrelerine doğrudan yazan bileşenler oluşturmaktan kaçının. Yukarıdaki NestedChild Bileşen, BoundValue doğrudan parametresine yazmak yerine bir özellik kullanır ChildMessage . Daha fazla bilgi için bkz. RazorASP.NET Core Bileşen.

Shared/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}");
    }
}

Bellekte ve iç içe geçmiş olmayan bileşenlerde veri paylaşmaya uygun alternatif bir yaklaşım için bkz ASP.NET Core Blazor durum yönetimi ..

Ek kaynaklar

Razor bileşenler, @bind Razor bir alan, özellik veya ifade değeri olan Directive özniteliğiyle veri bağlama özellikleri sağlar Razor .

Aşağıdaki örnek bağlanır:

  • <input>C# alanına bir öğe değeri inputValue .
  • <input>C# özelliğine ikinci bir öğe değeri InputValue .

Bir <input> öğe odağı kaybettiğinde, ilişkili alanı veya özelliği güncellenir.

Pages/Bind.razor:

@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, alanın veya özelliğin değerini değiştirme yanıt olarak değil, yalnızca bileşen işlendiğinde güncellenir. Bileşenler olay işleyicisi kodu yürütüldükten sonra kendilerini oluşturduğundan, 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 Birleşik olduğu konusunda bir gösterim olarak aşağıdaki örnek, InputValue özelliği ikinci <input> öğe value ve onchange özniteliklerine bağlar. <input>Aşağıdaki örnekteki ikinci öğe bir kavram tanıtımına sahiptir ve bileşenlere verileri nasıl bağlayacağınız konusunda önermemelidir Razor .

Pages/BindTheory.razor:

@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; }
}

BindTheoryBileşen işlendiğinde, value HTML Tanıtım <input> öğesinin InputValue özelliği özelliğinden gelir. Kullanıcı metin kutusuna bir değer girdiğinde ve öğe odağını değiştirdiğinde, onchange olay tetiklenir ve InputValue özellik değiştirilen değere ayarlanır. Gerçekte, @bind tür dönüştürmelerin gerçekleştirildiği durumları işlediği için kod yürütmesi daha karmaşıktır. Genel olarak, @bind bir ifadenin geçerli değerini bir value özniteliğiyle ilişkilendirir ve kayıtlı işleyiciyi kullanarak değişiklikleri işler.

Yer tutucu için DOM olayına sahip bir öznitelik ekleyerek diğer belge nesne modeli (DOM) olaylarına bir özellik veya alan bağlayın @bind:event="{EVENT}" {EVENT} . Aşağıdaki örnek, InputValue <input> öğenin oninput olayı tetiklendiğinde özelliği öğenin değerine bağlar. Öğe odağı kaybettiğinde başlatılan onchange olayınaksine, oninput metin kutusunun değeri değiştiğinde harekete geçirilir.

Page/BindEvent.razor:

@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:

  • @bind ve @bind:event geçerlidir.
  • @Bind/@Bind:Event(büyük harfler B ve E ) veya @BIND / @BIND:EVENT (tümü büyük harf) geçersiz.

<select>Öğe seçeneklerini C# nesne değerlerine bağlama null

Bir <select> öğe seçeneği değerini C# nesne değeri olarak göstermek için herhangi bir mümkün değildir null , çünkü:

  • HTML özniteliklerinin değerleri olamaz null . HTML olarak en yakın eşdeğeri, null ÖĞESINDEN html özniteliğinin yokluğunda olur value <option> .
  • <option>Özniteliği olmayan bir seçerken value , tarayıcı değeri bu öğenin metin içeriği olarak değerlendirir <option> .

BlazorFramework, aşağıdakileri içereceği varsayılan davranışı bastırmak için denenmez:

  • Çerçevede özel durum geçici çözümleri zinciri oluşturma.
  • Geçerli çerçeve davranışında son değişiklikler.

HTML 'deki en büyük plausible null eşdeğeri boş bir dizedir value . BlazorÇerçeve, null bir değerine iki yönlü bağlama yönelik boş dize dönüştürmelerini işler <select> .

Ayrıştırılamayan değerler

Bir Kullanıcı, bir veri sınırlama öğesine ayrıştırılamayan bir değer sağlıyorsa, bağlama olayı tetiklendiğinde, çözümlenemeyen değer otomatik olarak önceki değerine döndürülür.

Bir <input> öğenin int Başlangıç değeri olan bir türe bağlandığı aşağıdaki bileşeni göz önünde bulundurun 123 .

Pages/UnparsableValues.razor:

@page "/unparseable-values"

<p>
    <input @bind="inputValue" />
</p>

<p>
    <code>inputValue</code>: @inputValue
</p>

@code {
    private int inputValue = 123;
}

Varsayılan olarak, bağlama öğenin onchange olayına uygulanır. Kullanıcı, metin kutusu girişinin değerini olarak 123.45 güncelleştirdiğinde ve odağı değiştirirse, öğenin değeri tetiklendiğinde öğesine geri döndürülür 123 onchange . Değeri 123.45 özgün değeri yararına reddedildiğinde 123 , Kullanıcı değerinin kabul edilmediğini anlamıştır.

oninputEvent () için @bind:event="oninput" , bir değer yeniden sürümü, ayrıştırılamayan bir değer sunan herhangi bir tuş vuruşu sonrasında oluşur. oninputOlayı, bağlantılı bir türle hedeflerken int , bir kullanıcının nokta () karakteri yazmasının engellenmiş olması önlenir . . Bir nokta ( . ) karakteri hemen kaldırılır, bu nedenle Kullanıcı yalnızca tam sayılara izin verilen anında geri bildirim alır. Olay üzerindeki değerin geri döndürülmesi oninput ideal değil (örneğin, kullanıcının ayrıştırılamayan bir değeri temizlemeye izin verilmesi gerektiği durumlarda) <input> . Alternatifler şunlardır:

  • oninputOlayı kullanmayın. onchangeGeçersiz bir değer, öğe odağı kaybederene kadar geri döndürülmediğinde, varsayılan olayı kullanın.
  • Veya gibi null yapılabilir bir türe bağlayın int? string ve geçersiz girdileri işlemek için özel get ve set erişimci mantığını sağlayın.
  • Veya gibi bir form doğrulama bileşenikullanın InputNumber<TValue> InputDate<TValue> . Form doğrulama bileşenleri, geçersiz girdileri yönetmek için yerleşik destek sağlar. Form doğrulama bileşenleri:
    • Kullanıcının geçersiz giriş sağlamasına ve ilişkili doğrulama hatalarını almasına izin verin EditContext .
    • Kullanıcı ek WebForm verisi girmeye uğramadan doğrulama hatalarını Kullanıcı ARABIRIMINDE görüntüleyin.

Biçim dizeleri

Veri bağlama, kullanarak tek bir DateTime Biçim dizesiyle birlikte çalışarak @bind:format="{FORMAT STRING}" , {FORMAT STRING} yer tutucunun biçim dizesidir. Para birimi veya sayı biçimleri gibi diğer biçim ifadeleri şu anda kullanılamaz, ancak gelecekteki bir sürüme eklenebilir.

Pages/DateBinding.razor:

@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);
}

Yukarıdaki kodda, <input> öğesinin alan türü ( type özniteliği) varsayılan olarak olur text .

Null yapılabilir System.DateTime ve System.DateTimeOffset desteklenir:

private DateTime? date;
private DateTimeOffset? dateOffset;

date Blazor Tarihleri biçimlendirmek için yerleşik destek içerdiğinden, alan türü için bir biçim belirtmenin kullanılması önerilmez. Önerinin artma içinde, yyyy-MM-dd alan türüyle bir biçim sağlanırsa yalnızca bağlama için tarih biçimini kullanın date :

<input type="date" @bind="startDate" @bind:format="yyyy-MM-dd">

Özel bağlama biçimleri

C# get ve set erişimcileri , aşağıdaki bileşenin gösterdiği gibi özel bağlama biçimi davranışı oluşturmak için kullanılabilir DecimalBinding . Bileşen pozitif veya negatif bir ondalığa, bir <input> Özellik () yoluyla bir öğe için en fazla üç ondalık basamakla bağlar string DecimalValue .

Pages/DecimalBinding.razor:

@page "/decimal-binding"
@using System.Globalization

<p>
    <label>
        Decimal value (&plusmn;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);
            }
        }
    }
}

Bileşen parametreleriyle bağlama

Yaygın bir senaryo, alt bileşenin bir özelliğini üst bileşenindeki bir özelliğe bağlamadır. Birden çok bağlama düzeyi aynı anda gerçekleştiğinden, bu senaryoya zincirleme bağlama denir.

Bileşen parametreleri , bir üst bileşenin, @bind-{PROPERTY} {PROPERTY} yer tutucunun bağlanacak özellik olduğu sözdizimi ile bağlama özelliklerine izin verir.

Alt bileşende söz dizimi ile zincirleme bağlantıları uygulayamıyoruz @bind . Alt bileşenden üst öğe içindeki özelliği güncelleştirmeyi desteklemek için bir olay işleyicisi ve değeri ayrı olarak belirtilmelidir.

Üst bileşen, @bind alt bileşenle veri bağlamayı ayarlamak için söz dizimini kullanır.

Aşağıdaki ChildBind bileşen bir Year bileşen parametresi ve içerir EventCallback<TValue> . Kuralına göre parametresinin, EventCallback<TValue> "" sonekine sahip bileşen parametresi adı olarak adlandırılması gerekir Changed . Adlandırma söz dizimi, {PARAMETER NAME}Changed {PARAMETER NAME} yer tutucunun parametre adı olduğu yerdir. Aşağıdaki örnekte, olarak EventCallback<TValue> adlandırılmıştır YearChanged .

EventCallback.InvokeAsync Belirtilen bağımsız değişkenle bağlama ile ilişkili temsilciyi çağırır ve değiştirilen özellik için bir olay bildirimi gönderir.

Shared/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 {
    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));
    }
}

Olaylar ve hakkında daha fazla bilgi için EventCallback<TValue> , makalesinin eventcallback bölümüne bakın ASP.NET Core Blazor olay işleme .

Aşağıdaki Parent bileşende, year alanı Year alt bileşenin parametresine bağlanır. Parametrenin Year türüyle eşleşen bir yardımcı olayı olduğundan parametre bağlanabilir YearChanged Year .

Pages/Parent.razor:

@page "/Parent"

<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);
    }
}

Kural gereği, bir özellik, bir işleyiciye atanmış özniteliği dahil ederek karşılık gelen bir olay işleyicisine bağlanabilir; @bind-{PROPERTY}:event burada {PROPERTY} yer tutucu özelliktir. <ChildBind @bind-Year="year" /> yazmaya eşittir:

<ChildBind @bind-Year="year" @bind-Year:event="YearChanged" />

Daha gelişmiş ve gerçek dünyada bir örnekte aşağıdaki PasswordEntry bileşen:

  • Bir <input> öğenin değerini bir password alana ayarlar.
  • Bir özelliğin değişikliklerini, Password EventCallback alt öğenin geçerli değerinde bağımsız değişkeni olarak geçen bir üst bileşene gösterir password .
  • onclickYöntemini tetiklemek için olayını kullanır ToggleShowPassword . Daha fazla bilgi için bkz. ASP.NET Core Blazor olay işleme.

Shared/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="@(showPassword ? "text" : "password")"
                       value="@password" />
            </label>
        </p>
        <button class="btn btn-primary" @onclick="ToggleShowPassword">
            Show password
        </button>
    </div>
</div>

@code {
    private bool showPassword;
    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);
    }

    private void ToggleShowPassword()
    {
        showPassword = !showPassword;
    }
}

PasswordEntryBileşen, aşağıdaki bileşen örneği gibi başka bir bileşende kullanılır PasswordBinding .

Pages/PasswordBinding.razor:

@page "/password-binding"

<h1>Password Binding</h1>

<PasswordEntry @bind-Password="password" />

<p>
    <code>password</code>: @password
</p>

@code {
    private string password = "Not set";
}

PasswordBindingBileşen başlangıçta işlendiğinde, password değeri Not set Kullanıcı arabiriminde görüntülenir. İlk işlemeden sonra, değeri password Password bileşendeki bileşen parametre değerinde yapılan değişiklikleri yansıtır PasswordEntry .

Not

Yukarıdaki örnek, parolayı tek yönlü alt PasswordEntry bileşenden üst PasswordBinding bileşene bağlar. Bu senaryoda iki yönlü bağlama, hedef uygulamanın, yalnızca parolayı üst öğeye geçiren bir paylaşılan parola girişi bileşenine sahip olması durumunda bir gereklilik değildir. Doğrudan alt bileşenin parametresine yazmadaniki yönlü bağlamaya izin veren bir yaklaşım için, NestedChild Bu makalenin ikiden fazla bileşenden bağlama bölümünde bileşen örneğine bakın.

İşleyicide denetimleri veya tuzak hatalarını gerçekleştirin. Aşağıdaki düzeltilen PasswordEntry Bileşen, parolanın değerinde bir boşluk kullanılıyorsa kullanıcıya anında geri bildirim sağlar.

Shared/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="@(showPassword ? "text" : "password")"
                       value="@password" />
            </label>
            <span class="text-danger">@validationMessage</span>
        </p>
        <button class="btn btn-primary" @onclick="ToggleShowPassword">
            Show password
        </button>
    </div>
</div>

@code {
    private bool showPassword;
    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);
        }
    }

    private void ToggleShowPassword()
    {
        showPassword = !showPassword;
    }
}

İkiden fazla bileşen arasında bağlama

Parametreleri herhangi bir sayıda iç içe bileşen aracılığıyla bağlayabilirsiniz, ancak tek yönlü verilerin akışını dikkate almanız gerekir:

  • Değişiklik bildirimleri hiyerarşinin akışını.
  • Yeni parametre değerleri hiyerarşinin altına akar.

Ortak ve önerilen bir yaklaşım, aşağıdaki örnekte gösterildiği gibi, hangi durumun güncellenmesi gerektiği hakkında karışıklık oluşmasını önlemek için yalnızca ana bileşende temel alınan verileri saklamaktır.

Pages/Parent.razor:

@page "/parent"

<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}";
    }
}

Shared/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="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ı

Genellikle, kendi bileşen parametrelerine doğrudan yazan bileşenler oluşturmaktan kaçının. Yukarıdaki NestedChild Bileşen, BoundValue doğrudan parametresine yazmak yerine bir özellik kullanır ChildMessage . Daha fazla bilgi için bkz. RazorASP.NET Core Bileşen.

Shared/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}");
    }
}

Bellekte ve iç içe geçmiş olmayan bileşenlerde veri paylaşmaya uygun alternatif bir yaklaşım için bkz ASP.NET Core Blazor durum yönetimi ..

Ek kaynaklar

Razor bileşenler, @bind Razor bir alan, özellik veya ifade değeri olan Directive özniteliğiyle veri bağlama özellikleri sağlar Razor .

Aşağıdaki örnek bağlanır:

  • <input>C# alanına bir öğe değeri inputValue .
  • <input>C# özelliğine ikinci bir öğe değeri InputValue .

Bir <input> öğe odağı kaybettiğinde, ilişkili alanı veya özelliği güncellenir.

Pages/Bind.razor:

@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, alanın veya özelliğin değerini değiştirme yanıt olarak değil, yalnızca bileşen işlendiğinde güncellenir. Bileşenler olay işleyicisi kodu yürütüldükten sonra kendilerini oluşturduğundan, 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 Birleşik olduğu konusunda bir gösterim olarak aşağıdaki örnek, InputValue özelliği ikinci <input> öğe value ve onchange özniteliklerine bağlar. <input>Aşağıdaki örnekteki ikinci öğe bir kavram tanıtımına sahiptir ve bileşenlere verileri nasıl bağlayacağınız konusunda önermemelidir Razor .

Pages/BindTheory.razor:

@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; }
}

BindTheoryBileşen işlendiğinde, value HTML Tanıtım <input> öğesinin InputValue özelliği özelliğinden gelir. Kullanıcı metin kutusuna bir değer girdiğinde ve öğe odağını değiştirdiğinde, onchange olay tetiklenir ve InputValue özellik değiştirilen değere ayarlanır. Gerçekte, @bind tür dönüştürmelerin gerçekleştirildiği durumları işlediği için kod yürütmesi daha karmaşıktır. Genel olarak, @bind bir ifadenin geçerli değerini bir value özniteliğiyle ilişkilendirir ve kayıtlı işleyiciyi kullanarak değişiklikleri işler.

Yer tutucu için DOM olayına sahip bir öznitelik ekleyerek diğer belge nesne modeli (DOM) olaylarına bir özellik veya alan bağlayın @bind:event="{EVENT}" {EVENT} . Aşağıdaki örnek, InputValue <input> öğenin oninput olayı tetiklendiğinde özelliği öğenin değerine bağlar. Öğe odağı kaybettiğinde başlatılan onchange olayınaksine, oninput metin kutusunun değeri değiştiğinde harekete geçirilir.

Page/BindEvent.razor:

@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:

  • @bind ve @bind:event geçerlidir.
  • @Bind/@Bind:Event(büyük harfler B ve E ) veya @BIND / @BIND:EVENT (tümü büyük harf) geçersiz.

<select>Öğe seçeneklerini C# nesne değerlerine bağlama null

Bir <select> öğe seçeneği değerini C# nesne değeri olarak göstermek için herhangi bir mümkün değildir null , çünkü:

  • HTML özniteliklerinin değerleri olamaz null . HTML olarak en yakın eşdeğeri, null ÖĞESINDEN html özniteliğinin yokluğunda olur value <option> .
  • <option>Özniteliği olmayan bir seçerken value , tarayıcı değeri bu öğenin metin içeriği olarak değerlendirir <option> .

BlazorFramework, aşağıdakileri içereceği varsayılan davranışı bastırmak için denenmez:

  • Çerçevede özel durum geçici çözümleri zinciri oluşturma.
  • Geçerli çerçeve davranışında son değişiklikler.

BlazorÇerçeve, null iki yönlü bir değere bağlamayı denerken boş dize dönüştürmeleri için otomatik olarak işleme yapmaz <select> . Daha fazla bilgi için bkz. <select> null değere bağlamayı çözme (DotNet/aspnetcore #23221).

Ayrıştırılamayan değerler

Bir Kullanıcı, bir veri sınırlama öğesine ayrıştırılamayan bir değer sağlıyorsa, bağlama olayı tetiklendiğinde, çözümlenemeyen değer otomatik olarak önceki değerine döndürülür.

Bir <input> öğenin int Başlangıç değeri olan bir türe bağlandığı aşağıdaki bileşeni göz önünde bulundurun 123 .

Pages/UnparsableValues.razor:

@page "/unparseable-values"

<p>
    <input @bind="inputValue" />
</p>

<p>
    <code>inputValue</code>: @inputValue
</p>

@code {
    private int inputValue = 123;
}

Varsayılan olarak, bağlama öğenin onchange olayına uygulanır. Kullanıcı, metin kutusu girişinin değerini olarak 123.45 güncelleştirdiğinde ve odağı değiştirirse, öğenin değeri tetiklendiğinde öğesine geri döndürülür 123 onchange . Değeri 123.45 özgün değeri yararına reddedildiğinde 123 , Kullanıcı değerinin kabul edilmediğini anlamıştır.

oninputEvent () için @bind:event="oninput" , bir değer yeniden sürümü, ayrıştırılamayan bir değer sunan herhangi bir tuş vuruşu sonrasında oluşur. oninputOlayı, bağlantılı bir türle hedeflerken int , bir kullanıcının nokta () karakteri yazmasının engellenmiş olması önlenir . . Bir nokta ( . ) karakteri hemen kaldırılır, bu nedenle Kullanıcı yalnızca tam sayılara izin verilen anında geri bildirim alır. Olay üzerindeki değerin geri döndürülmesi oninput ideal değil (örneğin, kullanıcının ayrıştırılamayan bir değeri temizlemeye izin verilmesi gerektiği durumlarda) <input> . Alternatifler şunlardır:

  • oninputOlayı kullanmayın. onchangeGeçersiz bir değer, öğe odağı kaybederene kadar geri döndürülmediğinde, varsayılan olayı kullanın.
  • Veya gibi null yapılabilir bir türe bağlayın int? string ve geçersiz girdileri işlemek için özel get ve set erişimci mantığını sağlayın.
  • Veya gibi bir form doğrulama bileşenikullanın InputNumber<TValue> InputDate<TValue> . Form doğrulama bileşenleri, geçersiz girdileri yönetmek için yerleşik destek sağlar. Form doğrulama bileşenleri:
    • Kullanıcının geçersiz giriş sağlamasına ve ilişkili doğrulama hatalarını almasına izin verin EditContext .
    • Kullanıcı ek WebForm verisi girmeye uğramadan doğrulama hatalarını Kullanıcı ARABIRIMINDE görüntüleyin.

Biçim dizeleri

Veri bağlama, kullanarak tek bir DateTime Biçim dizesiyle birlikte çalışarak @bind:format="{FORMAT STRING}" , {FORMAT STRING} yer tutucunun biçim dizesidir. Para birimi veya sayı biçimleri gibi diğer biçim ifadeleri şu anda kullanılamaz, ancak gelecekteki bir sürüme eklenebilir.

Pages/DateBinding.razor:

@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> öğesinin alan türü ( type özniteliği) varsayılan olarak olur text .

Null yapılabilir System.DateTime ve System.DateTimeOffset desteklenir:

private DateTime? date;
private DateTimeOffset? dateOffset;

date Blazor Tarihleri biçimlendirmek için yerleşik destek içerdiğinden, alan türü için bir biçim belirtmenin kullanılması önerilmez. Önerinin artma içinde, yyyy-MM-dd alan türüyle bir biçim sağlanırsa yalnızca bağlama için tarih biçimini kullanın date :

<input type="date" @bind="startDate" @bind:format="yyyy-MM-dd">

Özel bağlama biçimleri

C# get ve set erişimcileri , aşağıdaki bileşenin gösterdiği gibi özel bağlama biçimi davranışı oluşturmak için kullanılabilir DecimalBinding . Bileşen pozitif veya negatif bir ondalığa, bir <input> Özellik () yoluyla bir öğe için en fazla üç ondalık basamakla bağlar string DecimalValue .

Pages/DecimalBinding.razor:

@page "/decimal-binding"
@using System.Globalization

<p>
    <label>
        Decimal value (&plusmn;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);
            }
        }
    }
}

Bileşen parametreleriyle bağlama

Yaygın bir senaryo, alt bileşenin bir özelliğini üst bileşenindeki bir özelliğe bağlamadır. Birden çok bağlama düzeyi aynı anda gerçekleştiğinden, bu senaryoya zincirleme bağlama denir.

Bileşen parametreleri , bir üst bileşenin, @bind-{PROPERTY} {PROPERTY} yer tutucunun bağlanacak özellik olduğu sözdizimi ile bağlama özelliklerine izin verir.

Alt bileşende söz dizimi ile zincirleme bağlantıları uygulayamıyoruz @bind . Alt bileşenden üst öğe içindeki özelliği güncelleştirmeyi desteklemek için bir olay işleyicisi ve değeri ayrı olarak belirtilmelidir.

Üst bileşen, @bind alt bileşenle veri bağlamayı ayarlamak için söz dizimini kullanır.

Aşağıdaki ChildBind bileşen bir Year bileşen parametresi ve içerir EventCallback<TValue> . Kuralına göre parametresinin, EventCallback<TValue> "" sonekine sahip bileşen parametresi adı olarak adlandırılması gerekir Changed . Adlandırma söz dizimi, {PARAMETER NAME}Changed {PARAMETER NAME} yer tutucunun parametre adı olduğu yerdir. Aşağıdaki örnekte, olarak EventCallback<TValue> adlandırılmıştır YearChanged .

EventCallback.InvokeAsync Belirtilen bağımsız değişkenle bağlama ile ilişkili temsilciyi çağırır ve değiştirilen özellik için bir olay bildirimi gönderir.

Shared/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 {
    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));
    }
}

Olaylar ve hakkında daha fazla bilgi için EventCallback<TValue> , makalesinin eventcallback bölümüne bakın ASP.NET Core Blazor olay işleme .

Aşağıdaki Parent bileşende, year alanı Year alt bileşenin parametresine bağlanır. Parametrenin Year türüyle eşleşen bir yardımcı olayı olduğundan parametre bağlanabilir YearChanged Year .

Pages/Parent.razor:

@page "/Parent"

<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);
    }
}

Kural gereği, bir özellik, bir işleyiciye atanmış özniteliği dahil ederek karşılık gelen bir olay işleyicisine bağlanabilir; @bind-{PROPERTY}:event burada {PROPERTY} yer tutucu özelliktir. <ChildBind @bind-Year="year" /> yazmaya eşittir:

<ChildBind @bind-Year="year" @bind-Year:event="YearChanged" />

Daha gelişmiş ve gerçek dünyada bir örnekte aşağıdaki PasswordEntry bileşen:

  • Bir <input> öğenin değerini bir password alana ayarlar.
  • Bir özelliğin değişikliklerini, Password EventCallback alt öğenin geçerli değerinde bağımsız değişkeni olarak geçen bir üst bileşene gösterir password .
  • onclickYöntemini tetiklemek için olayını kullanır ToggleShowPassword . Daha fazla bilgi için bkz. ASP.NET Core Blazor olay işleme.

Shared/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="@(showPassword ? "text" : "password")"
                       value="@password" />
            </label>
        </p>
        <button class="btn btn-primary" @onclick="ToggleShowPassword">
            Show password
        </button>
    </div>
</div>

@code {
    private bool showPassword;
    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);
    }

    private void ToggleShowPassword()
    {
        showPassword = !showPassword;
    }
}

PasswordEntryBileşen, aşağıdaki bileşen örneği gibi başka bir bileşende kullanılır PasswordBinding .

Pages/PasswordBinding.razor:

@page "/password-binding"

<h1>Password Binding</h1>

<PasswordEntry @bind-Password="password" />

<p>
    <code>password</code>: @password
</p>

@code {
    private string password = "Not set";
}

PasswordBindingBileşen başlangıçta işlendiğinde, password değeri Not set Kullanıcı arabiriminde görüntülenir. İlk işlemeden sonra, değeri password Password bileşendeki bileşen parametre değerinde yapılan değişiklikleri yansıtır PasswordEntry .

Not

Yukarıdaki örnek, parolayı tek yönlü alt PasswordEntry bileşenden üst PasswordBinding bileşene bağlar. Bu senaryoda iki yönlü bağlama, hedef uygulamanın, yalnızca parolayı üst öğeye geçiren bir paylaşılan parola girişi bileşenine sahip olması durumunda bir gereklilik değildir. Doğrudan alt bileşenin parametresine yazmadaniki yönlü bağlamaya izin veren bir yaklaşım için, NestedChild Bu makalenin ikiden fazla bileşenden bağlama bölümünde bileşen örneğine bakın.

İşleyicide denetimleri veya tuzak hatalarını gerçekleştirin. Aşağıdaki düzeltilen PasswordEntry Bileşen, parolanın değerinde bir boşluk kullanılıyorsa kullanıcıya anında geri bildirim sağlar.

Shared/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="@(showPassword ? "text" : "password")"
                       value="@password" />
            </label>
            <span class="text-danger">@validationMessage</span>
        </p>
        <button class="btn btn-primary" @onclick="ToggleShowPassword">
            Show password
        </button>
    </div>
</div>

@code {
    private bool showPassword;
    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);
        }
    }

    private void ToggleShowPassword()
    {
        showPassword = !showPassword;
    }
}

İkiden fazla bileşen arasında bağlama

Parametreleri herhangi bir sayıda iç içe bileşen aracılığıyla bağlayabilirsiniz, ancak tek yönlü verilerin akışını dikkate almanız gerekir:

  • Değişiklik bildirimleri hiyerarşisinde yukarı doğru akar.
  • Yeni parametre değerleri hiyerarşisinde aşağı doğru akar.

Yaygın ve önerilen yaklaşımlardan biri, aşağıdaki örnekte gösterildiği gibi güncelleştirilen durumla ilgili kafa karışıklığını önlemek için yalnızca temel alınan verileri ana bileşende depolamaktır.

Pages/Parent.razor:

@page "/parent"

<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}";
    }
}

Shared/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="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 yazacak bileşenler oluşturmaktan kaçının. Yukarıdaki NestedChild bileşen, doğrudan BoundValue parametresine yazmak yerine bir özelliği ChildMessage kullanır. Daha fazla bilgi için bkz. RazorASP.NET Core Bileşen.

Shared/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}");
    }
}

Bellekte ve iç içe geçmiş olması gerek olmayan bileşenler arasında veri paylaşımına uygun alternatif bir yaklaşım için bkz. ASP.NET Core Blazor durum yönetimi .

Ek kaynaklar