如何在服务器端Blazor中实现DataGrid组件?

时间:2020-03-23 19:51:13

标签: c# blazor

我想在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的网格组件。但是,我需要更复杂的东西,因为我想建立排序功能,您可以单击列标题并让网格组件为您进行排序。

0 个答案:

没有答案