简体   繁体   English

Blazor 子到父事件回调<list<string> &gt; 不触发</list<string>

[英]Blazor Child to Parent EventCallback<List<string>> not triggering

I'm creating a shared component for a multi-select dropdown in Blazor server-side.我正在为 Blazor 服务器端的多选下拉菜单创建一个共享组件。 SelectMultiple.razor child component is not passing selected values back to the parent index.razor page. SelectMultiple.razor 子组件未将选定值传递回父 index.razor 页面。 EventCallback<List> SelectedItemChanged in child component doesn't seem to be triggering.子组件中的 EventCallback<List> SelectedItemChanged 似乎没有触发。 Can anyone help me out please?谁能帮帮我?

Below is SelectMultiple.razor下面是 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;
}

Here's my index.razor这是我的索引。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);
    }
}

This happens because you raise the event only when the List<string> variable changes, which in your code happens only once, during component's initialisation.发生这种情况是因为您仅在List<string>变量更改时引发事件,这在您的代码中仅在组件初始化期间发生一次。

The source of confusion is that, during the entire component's lifetime, this List variable points to the same object, so it doesn't change .混淆的根源在于,在整个组件的生命周期中,这个List变量指向同一个 object,所以它不会改变 The contents of that list changes, yes, but not the reference to the List itself.该列表的内容会更改,是的,但不会更改对List本身的引用。

As a starting point, I recommend to add the InvokeAsync() to the FilteredItemChanged() function.作为起点,我建议将InvokeAsync()添加到FilteredItemChanged() function。 You can figure out the rest from here.您可以从这里找出 rest。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM