如何在不知道属性名称和类型的情况下过滤 blazor 组件中的通用列表参数 [英] How to filter generic list parameter in a blazor component without knowing its property name and types
问题描述
下面是一个带有搜索输入的无序列表,可在您键入时过滤列表.一切正常:
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
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 Change the FetchData 然后将以下组件添加到您的应用中 Then add the following component to your app 您应该能够根据自己的需要进行调整. You should be able to adapt this to your needs. 这篇关于如何在不知道属性名称和类型的情况下过滤 blazor 组件中的通用列表参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! 标记更改为以下内容:
<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>
@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;
}
}
登录
关闭