blazor - Blazor 网格绑定列按字段名称
问题描述
我正在研究一些付费网格组件,它们有一个非常酷的“绑定列”技术:
<TelerikGrid Data=@GridData>
<GridColumns>
<GridColumn Field="TemperatureC" Title="Temp. C" />
<GridColumn Field="Summary" />
</GridColumns>
<GridToolBar>
<GridCommandButton Command="Add" Icon="add">Add Forecast</GridCommandButton>
</GridToolBar>
</TelerikGrid>
<DxDataGrid Data="@DataSource">
<DxDataGridColumn Field="@nameof(ProductFlat.Id)">
</DxDataGridColumn>
<DxDataGridColumn Field="@nameof(ProductFlat.Category)">
</DxDataGridColumn>
</DxDataGrid>
我怎样才能做到这一点?我想创建一个非常基本的表:
<MyGrid DataSource=@MySource>
<MyColumn Field="Id" Name="My Id" />
</MyGrid>
渲染:
<table class="table">
<thead>
<tr>
<th scope="col">My Id</th>
</tr>
</thead>
<tbody>
<tr>
<td>#1</td>
</tr>
<tr>
<td>#2</td>
</tr>
</tbody>
</table>
解决方案
这不是一个简单的解决方案,您应该了解 Blazor 如何使用组件。基本上,方法是MyColumn
在外部组件上注册子“模板” MyGrid
,然后通过一些反射动态渲染网格。下面我发布准备复制粘贴的食谱,测试和学习。
步骤 0:创建模板化 blazor 演示:
dotnet new blazorserver
第 1 步:创建Pages/MyColumn.razor
组件:
@code {
[Parameter]
public string Field { get; set; }
[CascadingParameter]
private MyGrid Parent { get; set; }
protected override void OnInitialized()
{
base.OnInitialized();
Parent.AddColumn(this); //register child into parent
}
}
第 2 步:创建Pages/MyGrid.razor
组件:
<CascadingValue Value="this">
<table class="table">
<tbody>
@ChildContent
@foreach (var item in DataSource)
{
@RowItem(item)
}
</tbody>
</table>
</CascadingValue>
@code {
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter]
public IEnumerable<object> DataSource { get; set; }
List<MyColumn> Columns = new List<MyColumn>();
public void AddColumn(MyColumn column)
{
Columns.Add(column);
StateHasChanged();
}
// Here the function to create each row dynamically:
private RenderFragment RowItem(object row)
{
int i = 0;
return b => // create dynamically
{
b.OpenElement(++i, "tr");
foreach(var column in Columns)
{
b.OpenElement(++i, "td");
var val = row.GetType().GetProperty(column.Field)
.GetValue(row, null).ToString();
b.AddContent(++i,val);
b.CloseElement();
}
b.CloseElement();
};
}
}
第 3 步:使用您的网格Pages/FetchData.razor
@page "/fetchdata"
@using s.Data
@inject WeatherForecastService ForecastService
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from a service.</p>
@if (forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
<MyGrid DataSource=@forecasts>
<MyColumn Field="Date"/>
<MyColumn Field="Summary"/>
</MyGrid>
}
@code {
private WeatherForecast[] forecasts;
protected override async Task OnInitializedAsync()
{
forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
}
}