在过滤的递归列表中包含父项

Include parents in filtered recursive list

目标是过滤递归列表。当用户搜索 Bar 时,应显示 Foo -> Bar。同样,当搜索词是 Baz 时,Foo -> Bar -> Baz 应该包含在结果中。

我的想法是遍历结果并将父项(如果有)添加到结果中。但这必须以递归方式完成。是否有使用 linq 的更简单的解决方案?你有什么想法?

我尝试过的:

游乐场:https://try.mudblazor.com/snippet/GaGQYokTnQPmRIHO

Main.razor

<MudTextField 
    T="string" 
    DebounceInterval="500" 
    Clearable="true" 
    Placeholder="Search" 
    Margin="Margin.Dense" 
    Variant="Variant.Outlined" 
    Adornment="Adornment.Start" 
    AdornmentIcon="@Icons.Filled.Search"
    ValueChanged="@(s => SearchTerm = s)"/>

<CascadingValue Value="Items.Where(i => (!string.IsNullOrEmpty(SearchTerm)) ? i.Name.Contains(SearchTerm) : true).ToArray()">
    <ItemList Parent="0"/>
</CascadingValue>

@code {

    public string? SearchTerm { get; set; } = string.Empty;

    public Item[]? Items = 
    { 
        new Item { Id = 1, Name = "Foo", Parent = 0 },
        new Item { Id = 2, Name = "Bar", Parent = 1 },
        new Item { Id = 3, Name = "Baz", Parent = 2 },
    };
}

ItemList.razor

@foreach(var item in Items.Where(i => i.Parent == Parent))
{
    @if (Items.Where(i => i.Parent == item.Id).Any())
    {
        <MudNavGroup Title="@item.Name">
            <ItemList Parent="@item.Id"/>
        </MudNavGroup>
    }
    else
    {
        <MudNavLink Href="@("/items/" + item.Id)">@item.Name</MudNavLink>
    }
}        

@code {
    [Parameter] public int? Parent { get; set; }

    [CascadingParameter] public Item[]? Items { get; set; }
}

Item.cs

public class Item
{
    public int Id { get; set; }

    public string? Name { get; set; }

    public int? Parent { get; set; }
}

您可以添加函数 Filter 或在 @code 中使用适当的名称,如下所示。并更新 <CascadingValue Value="Filter(SearchTerm)"> 解释在评论中。

<CascadingValue Value="Filter(SearchTerm)">
    <ItemList Parent="0"/>
</CascadingValue>

public Item[] Filter(string SearchTerm)
{
    // Get filtered list. Return all values when SearchTerm is null or empty else return matching values only
    var a = Items.Where(i => string.IsNullOrEmpty(SearchTerm) || i.Name.Contains(SearchTerm)).ToList();

    // NOTE : Add children first then only search for parent
    // Use condition to find all children hierarchy of any object which is not exist in the list
    while (Items.Any(i => a.Any(x => x.Id == i.Parent) && !a.Any(x => x.Id == i.Id)))
    {
        // Add complete children hierarchy for selected iterms
        a.AddRange(Items.Where(i => a.Any(x => x.Id == i.Parent) && !a.Any(x => x.Id == i.Id)));
    }
    
    // Use condition to find parent of any object which is not exist in the list
    while (Items.Any(i => a.Any(x => x.Parent == i.Id) && !a.Any(x => x.Id == i.Id)))
    {
        // Add all parents who are not already added in list
        a.AddRange(Items.Where(i => a.Any(x => x.Parent == i.Id) && !a.Any(x => x.Id == i.Id)));
    }

    // return final object
    return a.ToArray();
}