繁体   English   中英

如何在不知道其属性名称和类型的情况下过滤 blazor 组件中的通用列表参数

[英]How to filter generic list parameter in a blazor component without knowing its property name and types

下面是一个无序列表,其中包含一个搜索输入,可在您键入时过滤列表。 一切都很完美:

@page "/todolist"

<input @bind-value="SearchTerm" @bind-value:event="oninput" />

<span class="text-muted ml-5">
    Showing @FilteredToDos.Count out of @ToDoItems.Count
</span>

<h4 class="mt-4">To Do's</h4>
<ul>
    @foreach (var toDo in FilteredToDos)
    {
        <li>@toDo.Name</li>
    }
</ul>

@code {
    // Initialize SearchTerm to "" to prevent null's
    string SearchTerm { get; set; } = "";

    // Data
    class ToDoItem
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    List<ToDoItem> ToDoItems => new List<ToDoItem>
    {
        new ToDoItem {Id = 1, Name = "Garbage" },
        new ToDoItem {Id = 2, Name = "Dishes" },
        new ToDoItem {Id = 3, Name = "Wash clothes" },
        new ToDoItem {Id = 4, Name = "Water flowers" }
    };
    //filter
    List<ToDoItem> FilteredToDos => ToDoItems.Where(i => i.Name.ToLower().Contains(SearchTerm.ToLower())).ToList();
}

我将列表分成它自己的组件 (TodoComponent):

@typeparam TItem

<input @bind-value="SearchTerm" @bind-value:event="oninput" />

<h4 class="mt-4">To Do's</h4>
<ul>
    @foreach (var toDo in Todos)
    {
        @UnorderedList(toDo)
    }
</ul>

@code {
    [Parameter]
    public List<TItem> Todos { get; set; }
    [Parameter]
    public RenderFragment<TItem> UnorderedList { get; set; }

    string SearchTerm { get; set; } = "";

    List<TItem> FilteredToDos => Todos.Where(i => i.Name.ToLower().Contains(SearchTerm.ToLower())).ToList();
}

我在这里调用 blazor 组件:

@page "/todo"

    <TodoComponent Todos="@ToDoItems">
        <UnorderedList>
            <li>ID: @context.Id Name: @context.Name </li>
        </UnorderedList>
    </TodoComponent>

@code {
    private List<ToDoItem> ToDoItems => new List<ToDoItem>
        {
            new ToDoItem {Id = 1, Name = "Garbage" },
            new ToDoItem {Id = 2, Name = "Dishes" },
            new ToDoItem {Id = 3, Name = "Wash clothes" },
            new ToDoItem {Id = 4, Name = "Water flowers" }
        };

    public class ToDoItem
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

}

该列表显示正常,但我无法再过滤该列表。 我不想将过滤器 function 放在组件外部。 根据组件内的名称或 ID 进行过滤的最佳方法是什么? 使用不同的数据结构而不是列表会更好吗?

将参数属性添加到名为GetFilterData的组件中,它是Func<TItem, string>

然后您可以对每个项目调用GetFilterData来决定是否应该包含它。

将标准模板 Blazor 应用程序中的 FetchData <table>标记更改为以下内容:

    <table class="table">
        <thead>
            <tr>
                <th>Date</th>
                <th>Temp. (C)</th>
                <th>Temp. (F)</th>
                <th>Summary</th>
            </tr>
        </thead>
        <tbody>
            <MyList Items=@forecasts GetFilterableText=@(item => $"{item.Date} {item.Summary} {item.TemperatureC} {item.TemperatureF}" )>
                <tr>
                    <td>@context.Date.ToShortDateString()</td>
                    <td>@context.TemperatureC</td>
                    <td>@context.TemperatureF</td>
                    <td>@context.Summary</td>
                </tr>
            </MyList>
        </tbody>
    </table>

然后将以下组件添加到您的应用程序

@typeparam TItem

<input @bind=Filter @bind:event="oninput" />
@foreach (TItem item in GetFilteredItems())
{
    if (ChildContent == null)
    {
        <li>@item?.ToString()</li>
    }
    else
    {
        @ChildContent(item);
    }
}

@code {
        [Parameter]
        public IEnumerable<TItem> Items { get; set; }

        [Parameter]
        public Func<TItem, string> GetFilterableText { get; set; }

        [Parameter]
        public RenderFragment<TItem> ChildContent { get; set; }

    private string Filter;
    private static readonly Func<TItem, string> DefaultGetFilterableText =
        item => (item?.ToString() ?? "");


    private IEnumerable<TItem> GetFilteredItems()
    {
        Func<TItem, string> filterFunc = GetFilterableText ?? DefaultGetFilterableText;
        IEnumerable<TItem> result = (Items ?? Array.Empty<TItem>());
        if (!string.IsNullOrEmpty(Filter))
        {
            result = result
                .Where(x =>
                    (GetFilterableText(x) ?? "")
                    .Contains(Filter, StringComparison.InvariantCultureIgnoreCase));
        }
        return result;
    }

}

您应该能够根据您的需要进行调整。

暂无
暂无

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

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