我想在Blazor中创建一个DataGrid组件,该组件可以像以下在Razor组件页面中一样使用。有人在https://github.com/dotnet/aspnetcore/issues/14886的Blazor GitHub问题跟踪器上问了同样的问题。我尝试使用此处列出的代码,但是发现直到顶部的代码运行之后,这些列才添加到DataTable中。结果,没有任何列被渲染。我认为发布示例代码的人可能一直在使用客户端Blazor(WebAssembly)。这是我能想到的唯一对他们有用的原因,但对我而言却不是。
我的问题是,在Blazor中创建复杂的UI组件的推荐方法是什么?我认为部分问题在于DataTableColumn是一个组件。但是,它实际上并不打算呈现。它只是用作执行实际渲染的DataTable的配置/参数数据。因此,我想知道这是否是Blazor设计的滥用。 Telerik和其他公司可以这样做。 https://demos.telerik.com/blazor-ui/grid/overview
Index.razor
@page "/users"
@using FolioLibrary
<fieldset>
<legend>Users</legend>
<DataTable Class="table" Data="@(folioContext.User2s.Take(10).Cast<dynamic>().ToList())">
<DataTableColumn Name="Id" Field="Id" Type="typeof(Guid)"></DataTableColumn>
<DataTableColumn Name="Name" Field="Name" Type="typeof(string)"></DataTableColumn>
<DataTableColumn>
<Template Context="item">
<a href="/@item.Id" class="btn">text</a>
</Template>
</DataTableColumn>
</DataTable>
@code
{
private FolioContext folioContext = new FolioContext();
}
DataTable.razor
<div class="col-12">
<CascadingValue Value="this">
<table class="@Class" id="@Id">
<thead>
<tr>
@ChildContent
</tr>
</thead>
<tbody>
@*@foreach (dynamic item in FilteredData.Skip((Page - 1) * PerPage).Take(PerPage))*@
@foreach (dynamic item in Data)
{
<tr>
@foreach (DataTableColumn column in Columns)
{
<td class="align-middle" width="@(column.Type == null ? "1%" : "")">
@if (column.Template is null)
{
@item.GetType().GetProperty(column.Field).GetValue(item, null)
}
else
{
@column.Template(item)
}
</td>
}
</tr>
}
</tbody>
</table>
</CascadingValue>
</div>
@code
{
[Parameter]
public string Class { get; set; }
[Parameter]
public string Id { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter]
public List<dynamic> Data
{
get => data;
set
{
data = value;
FilteredData = data;
}
}
[Parameter]
public int PerPage { get; set; } = 25;
[Parameter]
public int Page { get; set; } = 1;
[Parameter]
public RenderFragment<dynamic> Actions { get; set; }
List<DataTableColumn> Columns { get; set; } = new List<DataTableColumn>();
List<dynamic> FilteredData { get; set; }
List<dynamic> data;
public void AddColumn(DataTableColumn column)
{
Columns.Add(column);
}
public void RemoveColumn(DataTableColumn column)
{
Columns.Remove(column);
}
}
DataTableColumn.razor
@implements IDisposable
<th>
<span>@Name</span>
</th>
@code
{
[Parameter]
public string Name { get; set; }
[Parameter]
public string Field { get; set; }
[Parameter]
public Type Type { get; set; }
[Parameter]
public RenderFragment<dynamic> Template { get; set; }
[CascadingParameter]
DataTable DataTable { get; set; }
protected override void OnInitialized()
{
DataTable.AddColumn(this);
}
public void Dispose()
{
DataTable.RemoveColumn(this);
}
}
我临时添加了OnInitialized()
和OnAfterRender()
方法,以查看组件的创建顺序以及引发事件的时间,以下是顺序。
DataTable.OnInitialized
DataTableColumn.OnInitialized
DataTable.OnInitialized
DataTableColumn.OnInitialized
DataTable.OnAfterRender
DataTableColumn.OnAfterRender
我在想也许以后可以使用其他事件/方法来使其呈现,但是,呈现代码/ foreach循环位于Razor组件的主体中,而不是在回调方法中。
在尝试此操作之前,我有一个更简单的带有HeaderTemplate和ItemTemplate的网格组件。但是,我需要更复杂的东西,因为我想建立排序功能,您可以单击列标题并让网格组件为您进行排序。