本文介绍了如何在blazor组件中过滤通用列表参数而又不知道其属性名称和类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是一个无序列表,带有搜索输入,可在您键入内容时过滤列表.一切正常:

Below is an unordered list with a search input that filters the list as you type. Everything works perfectly:

@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):

I seperated the list into its own component (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组件:

I'm calling the blazor component here:

@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; }
    }

}

该列表显示正常,但是我不能再过滤该列表.我不想将过滤器功能放在组件之外.根据组件内部的名称或ID进行过滤的最佳方法是什么?使用其他数据结构代替列表会更好吗?

The list displays fine, however I cannot filter the list anymore. I don't want to put the filter function outside of the component. What would be the best way to filter based on Name or ID inside the component? Would it be better to use a different data structure instead of a list?

推荐答案

向名为 GetFilterData 的组件添加参数属性,该属性是 Func< TItem,string>

Add a parameter property to your component called GetFilterData that is a Func<TItem, string>

然后,您可以在每个项目上调用 GetFilterData 来确定是否应包含它.

Then you can call GetFilterData on each item to decide if you should include it or not.

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

Change the FetchData <table> markup in a standard template Blazor app to the following:

    <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>

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

Then add the following component to your app

@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;
    }

}

您应该能够使其适应您的需求.

You should be able to adapt this to your needs.

这篇关于如何在blazor组件中过滤通用列表参数而又不知道其属性名称和类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-24 15:57