我正在使用 Blazor,希望能够通过采用 lambda 表达式的 SortBy 参数按给定列对数据网格(表)进行排序。它看起来像这样:
<DataGrid Items="Orders">
<GridHeader>
<GridColumn Label="Order Number" SortBy="@(order => order.OrderNumber)" />
<GridColumn Label="Order Date" SortBy="@(order => order.Date)" />
<GridColumn Label="Order Status" SortBy="@(order => order.Status)" />
<GridColumn Label="Number of Line Items" SortBy="@(order => order.LineItems.Count)" />
</GridHeader>
<GridRow Context="order">
<td>@order.OrderNumber</td>
<td>@order.OrderDate</td>
<td>@order.Status</td>
<td>@order.LineItems.Count</td>
</GridRow>
</Table>
Grid 组件应该能够采用任何类型的
IEnumerable
(如 IEnumerable<Order>
),因此 <DataGrid>
组件应该具有与其行项目关联的通用类型,通过 @typeparam TableItem
设置。我遇到的问题是能够在 TableItem
GridColumn
参数中引用 SortBy
类型。我需要它,以便我的代码编辑器 (Visual Studio) 识别 TableItem
lambda 表达式中的 SortBy
类型,以便(在本例中)当我开始输入 SortBy="@(order => order.)"
时,它将订单识别为类型 Order
智能感知将显示该类型的属性。我认为该解决方案与使用级联参数 (CascadingValue
) 和 @typeparam
有关,但我一直无法让它工作,并且想知道 Blazor 是否存在当前限制,导致其无法工作(例如,请参阅 this github issues,该问题仍处于开放状态)。
这是否可能,如果可以,我应该在这里使用什么方法?
抱歉,我没有给你直接的答案,但你可以看到这个项目的可排序和可过滤表,包括 lambda 表达式。我正在我的项目中使用它,目前运行良好。希望您觉得它有用:)。 Blazor 可排序表。
我不完全理解 - 您是否想要指定每列如何单独排序,或者您想要指定通过网格中表示的实体的哪些属性来排序所有项目? 第一个没有意义,因为列之间没有任何关系。后者更有意义,并且实际上更接近我的做法,但我不会将其称为
SortBy
,我宁愿将其称为 Property
,因为您可以使用该表达式指定该列中表示的属性,但是让我详细说明一下...
通常,如何做到这一点在很大程度上取决于组件的构成方式。我自己也尝试开发一个 DataGrid 组件,最终我在 this 之上进行构建。我对它进行了很多定制,其中之一就是排序。它实际上比你想象的要容易得多。
链接中示例的工作方式是:您使用列上的表达式指定属性。然后可以编译该表达式并使用它来提取从指定实体表示的属性值(尝试深入研究代码,它位于 GridColumns
CellTemplate
中)。 <th>
和 <td>
元素正在与 RenderTreebuilder
一起构建。
现在要实现排序,您可以执行以下操作并在 DataGrid 上创建一个公共方法
.SortItems(Func<TEntity, object> sortFunc)
,该方法接受指定要排序的属性的 func。这可以是设置该列表示的属性时指定的表达式。 SortFunc
可以直接使用 .OrderBy()
和 .OrderByDescending()
应用于您的项目列表,然后再将其传递到标记。
// ChildGridColumn
// Method being called when clicking a column header, passes along property func
private void OnSort()
{
if (CompiledProperty != null)
ParentDataGrid?.SortItems(CompiledProperty);
}
// ParentGrid
// SortMode differentiating ascending and descending sort modes.
public enum SortMode
{
Ascending,
Descending,
}
// Method sets the specfified sortFunc, provided by the GridColumn
public void SortItems(Func<TEntity, object> sortFunc)
{
SortFunc = sortFunc;
if (SortMode == SortMode.Ascending)
SortMode = SortMode.Descending;
else if (SortMode == SortMode.Descending)
SortMode = SortMode.Ascending;
StateHasChanged();
}
// Method sorts according to the SortMode
private IEnumerable<TEntity> GetSortedItems()
{
return SortMode switch
{
SortMode.Descending => Items.OrderByDescending(SortFunc),
SortMode.Ascending or _ => Items.OrderBy(SortFunc),
};
}
如果您想知道如何向由
RenderTreeBuilder
构建的 HTML 元素添加事件处理程序,这里还有另一个简短的示例:
var style = GetHeaderStyle();
var clickEvent = EventCallback.Factory.Create<MouseEventArgs>(this, OnSort);
builder.OpenElement(0, "td");
builder.AddAttribute(1, "width", Width);
builder.AddAttribute(2, "style", style);
builder.AddAttribute(3, "onclick", clickEvent);
builder.AddAttribute(4, "onmouseleave", hoverEvent);
builder.AddContent(5, title);
builder.CloseElement();
你应该查一下,它很容易学习,并且有足够多的表达能力的资源。