簡體   English   中英

在 Blazor 中,如何在動態 model 中 @bind 然后觸發 @onchange

[英]In Blazor, How to @bind and then fire @onchange in a dynamic model

Model:

public class FiltersModel
{      
    public CheckBoxListWithTitle Brand { get; set; }
}

public class CheckBoxListWithTitle
{        
    public List<FilterCheckBox> CheckBoxes { get; set; }
}

public class FilterCheckBox
{        
    public string Value { get; set; }
    public bool Checked { get; set; }
}

Razor:

@foreach (var item in Model.Brand.CheckBoxes)
{
<label>
    @item.Value
    <input type="checkbox" @onchange="@FilterChangedBrand" />  
</label>
}

@代碼:

public FiltersModel Model { get; set; } // Initialized in OnParametersSet

private void FilterChangedBrand(UIChangeEventArgs e)
{
    string newCheckedBrand = e.Value.ToString();
    // Now How to Find and Set the relevant Model property to newCheckedBrand
    FiltersChanged?.Invoke(Model);
}

如何在 FilterChangedBrand 方法中找到相關的 Model 屬性並將其設置為 newCheckedBrand。

或者在復選框標記中使用 @bind="@item.Checked" ,然后在選中的 state 復選框更改時引發事件?

由於無法使用@bind 和@onchange,您必須純粹在代碼中進行更改。 最簡單的方法是使用 lambda 捕獲item

Razor

@foreach (var item in Model.Brand.CheckBoxes)
{
    <label>
        @item.Value
        <input type="checkbox" @onchange="(e) => FilterChangedBrand(item, e)" />
    </label>
}

@代碼

public FiltersModel Model { get; set; } // Initialized in OnParametersSet

public event Action<FiltersModel> FiltersChanged;

private void FilterChangedBrand(FilterCheckBox item, ChangeEventArgs e)
{
    // here you do work of @bind
    item.Checked = !item.Checked;
    string newCheckedBrand = e.Value.ToString();
    // Now How to Find and Set the relevant Model property to newCheckedBrand
    FiltersChanged?.Invoke(Model);
}

替代和更復雜的方法,如果您想使用例如 WPF 重用您的 UI,這可能會有所幫助,即將該事件級聯放置在 model 本身中。

public class CheckBoxListWithTitle
{
    private List<FilterCheckBox> items = new List<FilterCheckBox>();
    public IReadOnlyList<FilterCheckBox> CheckBoxes => items.AsReadOnly();

    public event EventHandler ModelChanged;

    public void Add(FilterCheckBox item)
    {
        item.CheckedChanged += this.Item_CheckedChanged;
        this.items.Add(item);
    }

    private void Item_CheckedChanged(object sender, EventArgs e)
    {
        ModelChanged.Invoke(this, EventArgs.Empty);
    }
}

public class FilterCheckBox
{
    public string Value { get; set; }
    public bool Checked { get; set; }

    public event EventHandler CheckedChanged;
}

如您所見, CheckBoxListWithTitle將處理所需事件的傳播。 在 Razor 你只訂閱CheckBoxListWithTitle.ModelChanged

另一種選擇是在有界 object 中使用 INotifyPropertyChanged 接口。

public class RowToApprove : INotifyPropertyChanged
{
    private bool _approved;
  
    public string AddressLine { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
  
    public bool Approved
    {
        get => _approved;
        set
        {
            if (value == _approved) return;
            _approved = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

然后在您的頁面中,注冊到 ItemOnPropertyChanged 事件。

  item.PropertyChanged += ItemOnPropertyChanged;

並在那里做你的工作:

private void ItemOnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    //Do something
}

您的項目可能如下所示:

<input type="checkbox" @bind-value="@(context.Approved)" />

感謝@bind-value:event ,這個答案實際上會做到這一點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM