Blazor网格按字段名绑定列

Blazor网格按字段名绑定列,blazor,blazor-server-side,blazor-client-side,Blazor,Blazor Server Side,Blazor Client Side,我正在研究一些付费网格组件,它们有一种非常酷的“绑定列”技术: <TelerikGrid Data=@GridData> <GridColumns> <GridColumn Field="TemperatureC" Title="Temp. C" /> <GridColumn Field="Summary" /> </GridColumns> <GridToolBar>

我正在研究一些付费网格组件,它们有一种非常酷的“绑定列”技术:

<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>

我的身份证
#1
#2

这不是一个简单的解决方案,您应该了解Blazor如何使用组件。基本上,方法是在外部
MyGrid
组件上注册子组件
MyColumn
“模板”,然后通过一点反射动态渲染网格。下面我发布的食谱准备复制粘贴,测试和学习

步骤0:创建模板化blazor演示: 步骤1:创建
页面/MyColumn.razor
组件: 步骤2:创建
页面/MyGrid.razor
组件: 步骤3:在
页面/FetchData.razor
@page”/fetchdata
@使用美国数据
@注入天气预报服务预报服务
天气预报
此组件演示如何从服务获取数据

@如果(预测==null) { 加载

} 其他的 { } @代码{ 私人天气预报[]预测; 受保护的重写异步任务OnInitializedAsync() { Forecast=await ForecastService.GetForecastSync(DateTime.Now); } }
结果:

提示:使用reflection@aguafrommars,是的,它是反射、CascadingValue、生命周期方法和动态RenderFragments的混合体:)@Danielrera我懒得提供完整的解决方案:D@aguafrommars,是的,我也等了几分钟才得到答案。。。但是这是一个有趣的练习。当然,反思是一条路,但是!如何将子内容反向工程到MyColumn的数组?我需要它来创建网格头好工作!更多背景:创建Blazor模板化组件我正在尝试实现这个绑定,我想知道如何将数据从SignalR Hub推送到这里?假设我有股票价格,成交量每秒都在变化。我希望所有用户(多个浏览器窗口)看到相同的数据。
dotnet new blazorserver
@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
    }
}
<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();
    }
    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();
        };
    }
}
@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);
    }
}