Blazor Child to Parent EventCallback<List<string>> 未触发

Blazor Child to Parent EventCallback<List<string>> not triggering

我正在 Blazor 服务器端为多 select 下拉菜单创建一个共享组件。 SelectMultiple.razor 子组件未将 selected 值传递回父 index.razor 页面。子组件中的 EventCallback SelectedItemChanged 似乎没有触发。谁能帮帮我吗?

下面是SelectMultiple.razor

<div>
    <div class="form-group mb-1">
        <button class="btn dropdown-toggle btn-light"
                @onclick="@ToggleSelectMultiple"
                title="@SelectedItemsText">
            @ButtonText
        </button>
    </div>
    <div hidden="@toggleSelectBox" class="border border-secondary rounded py-1">
        <div class="mx-1">
            <input class="form-control" @bind="FilterText" @bind:event="oninput" />
        </div>
        <div class="form-check mt-1">
            @foreach (var item in FilteredItems)
            {
                <label>
                    <input type="checkbox" class="mr-1" checked="@item.IsSelected"
                           @onchange="_e => { FilteredItemChanged(item.Item, _e.Value); }" />@item.Item
                    </label><br />
                }
        </div>
    </div>
</div>

@code{    
    //public class SelectedItem
    //{
    //    public string Item { get; set; }
    //    public bool IsSelected { get; set; }
    //}

    private string _filterText;
    private bool toggleSelectBox = true;
    private List<string> _selectedItems;

    [Parameter] public List<string> Elements { get; set; }
    [Parameter]
    public List<string> SelectedItems
    {
        get => _selectedItems;
        set
        {
            _selectedItems = value;
            SelectedItemChanged.InvokeAsync(SelectedItems);
        }
    }
    [Parameter] public EventCallback<List<string>> SelectedItemChanged { get; set; }

    public List<SelectedItem> FilteredItems { get; set; } = new();
    public string FilterText
    {
        get { return _filterText; }
        set
        {
            _filterText = value;
            if (!string.IsNullOrWhiteSpace(FilterText))
            {
                FilteredItems = Elements.Where(x => x.ToLower().Contains(FilterText))
                    .Select(x => new SelectedItem() { Item = x, IsSelected = SelectedItems.Contains(x) }).ToList();
            }
            else
            {
                FilteredItems = Elements.Select(x => new SelectedItem() { Item = x, IsSelected = SelectedItems.Contains(x) }).ToList();
            }
        }
    }
    public string SelectedItemsText { get; set; }
    public string ButtonText { get; set; } = "Nothing selected";

    protected override void OnInitialized()
    {
        Elements.ForEach(x => FilteredItems.Add(new SelectedItem() { Item = x }));
        base.OnInitialized();
    }

    public void FilteredItemChanged(string item, object checkedValue)
    {
        if ((bool)checkedValue)
        {
            SelectedItems.Add(item);
        }
        else
        {
            SelectedItems.Remove(item);
        }

        SelectedItemsText = SelectedItems.Any() ? string.Join(",", SelectedItems.Select(x => x)) : null;
        ButtonText = SelectedItems.Any()
            ? (SelectedItems.Count == 1 ? SelectedItemsText : $"{SelectedItems.Count} items selected")
            : "Nothing selected";
        StateHasChanged();
    }

    private void ToggleSelectMultiple()
    {
        toggleSelectBox = !toggleSelectBox;
        ClearSearchText();
    }

    private void ClearSearchText() => FilterText = null;
}

这是我的 index.razor

@page "/"
<SelectMultiple Elements="Elements" SelectedItems="SelectedElements" SelectedItemChanged="SelectionChanged" />

<p>@SelectionAsText</p>
@code{
    public List<string> Elements { get; set; } = new List<string>() { "dog", "cat", "mouse", "hippo", "rat", "giraffe" };
    public List<string> SelectedElements { get; set; } = new();
    private string SelectionAsText;

    public void SelectionChanged()
    {
        SelectionAsText = string.Join(",", SelectedElements);
    }
}

发生这种情况是因为您仅在 List<string> 变量更改时引发事件,这在您的代码中仅在组件初始化期间发生一次。

混淆的根源在于,在整个组件的生命周期中,这个 List 变量指向同一个对象,所以它不会 改变 。该列表的内容发生了变化,是的,但对 List 本身的引用没有变化。

作为起点,我建议将 InvokeAsync() 添加到 FilteredItemChanged() 函数。你可以从这里算出剩下的。

这个docs article explains the basics around parameter binding in Blazor. Also, check the answers to ,他们可能更容易理解一些。