Blazor (c#) DXDatagrid (devexpress):用图标替换默认命令按钮时主从编辑器出现问题
Blazor (c#) DXDatagrid (devexpress) : Problem with Master Detail editor when replacing the default command buttons with icons
我使用 Blazor 和 Devexpress DxDataGrid 组件创建了一个 C# 项目来创建主从视图。使用默认命令按钮(新建、编辑)一切正常。当我用图标替换主命令默认按钮时,我对编辑功能没有问题:
当我替换详细信息默认控件时,用于添加或替换行的详细信息编辑器不起作用:
当我保留默认命令按钮时,仅针对细节、主控(带有图标)和细节(带有默认按钮),所有主控和细节编辑器都可以正常工作:
要重现该问题,请下载并编译您可以在以下位置找到的 devexpress 项目:How to replace default command button with icons on DXDataGrid
该示例显示了如何替换单个网格中的默认按钮。在我的测试项目中,我添加了一个细节,如以下代码片段所示(只需替换 .razor 文件中的所有代码):
@page "/"
@using CommandButtonsWithIcons.Data
@inject WeatherForecastService ForecastService
@if (forecasts == null) {
<h1>Loading...</h1>
}
else {
<DxDataGrid Data=@forecasts ShowFilterRow=false CssClass="MainGrid" @ref="MyGrid" ShowDetailRow="true"
RowUpdating=@((updatingDataItem, newValues) => OnRowUpdating(updatingDataItem, newValues))
RowInserting=@((newValues) => OnRowInserting(newValues))>
<Columns>
<DxDataGridCommandColumn>
<HeaderCellTemplate>
<a class="oi oi-plus" @onclick="@(() => MyGrid.StartRowEdit(null))" href="javascript:void(0);"></a>
</HeaderCellTemplate>
<CellTemplate>
<a class="oi oi-pencil" @onclick="@(() => MyGrid.StartRowEdit(context))" href="javascript:void(0);"></a>
<a class="oi oi-x" @onclick="@(() => Delete(context as WeatherForecast))" href="javascript:void(0);"></a>
</CellTemplate>
</DxDataGridCommandColumn>
<DxDataGridColumn Field=@nameof(WeatherForecast.TemperatureC) Caption="Temp. (C)"></DxDataGridColumn>
<DxDataGridColumn Field=@nameof(WeatherForecast.TemperatureF) Caption="Temp. (F)"></DxDataGridColumn>
<DxDataGridComboBoxColumn Field=@nameof(WeatherForecast.Summary) Caption="Summary" Data=@summaries></DxDataGridComboBoxColumn>
<DxDataGridDateEditColumn Field=@nameof(WeatherForecast.Date) DisplayFormatString="dd/MM/yyyy"
EditFormatString="dd/MM/yyyy"></DxDataGridDateEditColumn>
</Columns>
<DetailRowTemplate Context="dataItem">
<DxDataGrid Data=@forecasts.Where(x=>x.TemperatureC==dataItem.TemperatureC) ShowFilterRow=false CssClass="MainGrid" @ref="MyGridDetail"
RowUpdating=@((updatingDataItem, newValues) => OnRowUpdating(updatingDataItem, newValues))
RowInserting=@((newValues) => OnRowInserting(newValues))>
<DxDataGridCommandColumn>
<HeaderCellTemplate>
<a class="oi oi-plus" @onclick="@(() => MyGridDetail.StartRowEdit(null))" href="javascript:void(0);"></a>
</HeaderCellTemplate>
<CellTemplate>
<a class="oi oi-pencil" @onclick="@(() => MyGridDetail.StartRowEdit(context))" href="javascript:void(0);"></a>
<a class="oi oi-x" @onclick="@(() => Delete(context as WeatherForecast))" href="javascript:void(0);"></a>
</CellTemplate>
</DxDataGridCommandColumn>
<DxDataGridColumn Field=@nameof(WeatherForecast.TemperatureC) Caption="Temp. (C)"></DxDataGridColumn>
<DxDataGridColumn Field=@nameof(WeatherForecast.TemperatureF) Caption="Temp. (F)"></DxDataGridColumn>
<DxDataGridComboBoxColumn Field=@nameof(WeatherForecast.Summary) Caption="Summary" Data=@summaries></DxDataGridComboBoxColumn>
<DxDataGridDateEditColumn Field=@nameof(WeatherForecast.Date) DisplayFormatString="dd/MM/yyyy"
EditFormatString="dd/MM/yyyy"></DxDataGridDateEditColumn>
</DxDataGrid>
</DetailRowTemplate>
</DxDataGrid>
}
@functions {
WeatherForecast[] forecasts;
string[] summaries;
DevExpress.Blazor.DxDataGrid<WeatherForecast> MyGrid;
DevExpress.Blazor.DxDataGrid<WeatherForecast> MyGridDetail;
protected override async Task OnInitializedAsync() {
forecasts = await ForecastService.GetForecastAsync();
summaries = await ForecastService.GetSummariesAsync();
}
async void OnRowUpdating(WeatherForecast dataItem, Dictionary<string, object> newValue) {
forecasts = await ForecastService.Update(dataItem, newValue);
}
async void OnRowInserting(Dictionary<string, object> newValue) {
forecasts = await ForecastService.Insert(newValue);
}
async void Delete(WeatherForecast item) {
if (item != null) {
forecasts = await ForecastService.Remove(item);
}
}
}
UPDATE 正如 devexpress 的 Paul V 建议的那样,我们必须创建一个新的 razor 组件来实现一个新的 DXDatagrid 组件实例,因为它不适合引用该组件,2或在同一个剃须刀组件上多次。因此,要解决此问题,请创建另一个组件(即 DetaiGrid)并在 DetailRowTemplate 中引用它并发送一个参数、主记录和详细信息源:
<DetailRowTemplate Context="dataItem">
<DetailGrid MasterRecord="@dataItem" ForecastService="@ForecastService" Forecasts="@forecasts" ></DetailGrid>
</DetailRowTemplate>
详细示例:
<h3>DetailGrid2</h3>
@using CommandButtonsWithIcons.Data
<DxDataGrid Data=@Forecasts.Where(x=>x.TemperatureC==MasterRecord.TemperatureC) ShowFilterRow=false CssClass="MainGrid" @ref="MyGridDetail"
RowUpdatingAsync=@(OnRowUpdating)
RowInsertingAsync=@(OnRowInserting)>
<DxDataGridCommandColumn>
<HeaderCellTemplate>
<a class="oi oi-plus" @onclick="@(() => MyGridDetail.StartRowEdit(null))" href="javascript:void(0);"></a>
</HeaderCellTemplate>
<CellTemplate>
<a class="oi oi-pencil" @onclick="@(() => MyGridDetail.StartRowEdit(context))" href="javascript:void(0);"></a>
</CellTemplate>
</DxDataGridCommandColumn>
<DxDataGridColumn Field=@nameof(WeatherForecast.TemperatureC) Caption="Temp. (C)"></DxDataGridColumn>
<DxDataGridColumn Field=@nameof(WeatherForecast.TemperatureF) Caption="Temp. (F)"></DxDataGridColumn>
<DxDataGridDateEditColumn Field=@nameof(WeatherForecast.Date) DisplayFormatString="dd/MM/yyyy"
EditFormatString="dd/MM/yyyy"></DxDataGridDateEditColumn>
</DxDataGrid>
@code {
[Parameter]
public WeatherForecast[] Forecasts { get; set; }
[Parameter]
public WeatherForecast MasterRecord{ get; set; }
[Parameter]
public WeatherForecastService ForecastService { get; set; }
DevExpress.Blazor.DxDataGrid<WeatherForecast> MyGridDetail = null;
async Task OnRowUpdating(WeatherForecast dataItem, IDictionary<string, object> newValue)
{
Forecasts = await ForecastService.Update(dataItem, newValue);
}
async Task OnRowInserting(IDictionary<string, object> newValue)
{
//forecasts = await ForecastService.Insert(newValue);
}
}
我不建议对多个实例使用一个 ref 变量。它可能会导致此类碰撞。将您的详细信息网格隔离在单独的组件中以解决该问题。
我使用 Blazor 和 Devexpress DxDataGrid 组件创建了一个 C# 项目来创建主从视图。使用默认命令按钮(新建、编辑)一切正常。当我用图标替换主命令默认按钮时,我对编辑功能没有问题:
当我替换详细信息默认控件时,用于添加或替换行的详细信息编辑器不起作用:
当我保留默认命令按钮时,仅针对细节、主控(带有图标)和细节(带有默认按钮),所有主控和细节编辑器都可以正常工作:
要重现该问题,请下载并编译您可以在以下位置找到的 devexpress 项目:How to replace default command button with icons on DXDataGrid 该示例显示了如何替换单个网格中的默认按钮。在我的测试项目中,我添加了一个细节,如以下代码片段所示(只需替换 .razor 文件中的所有代码):
@page "/"
@using CommandButtonsWithIcons.Data
@inject WeatherForecastService ForecastService
@if (forecasts == null) {
<h1>Loading...</h1>
}
else {
<DxDataGrid Data=@forecasts ShowFilterRow=false CssClass="MainGrid" @ref="MyGrid" ShowDetailRow="true"
RowUpdating=@((updatingDataItem, newValues) => OnRowUpdating(updatingDataItem, newValues))
RowInserting=@((newValues) => OnRowInserting(newValues))>
<Columns>
<DxDataGridCommandColumn>
<HeaderCellTemplate>
<a class="oi oi-plus" @onclick="@(() => MyGrid.StartRowEdit(null))" href="javascript:void(0);"></a>
</HeaderCellTemplate>
<CellTemplate>
<a class="oi oi-pencil" @onclick="@(() => MyGrid.StartRowEdit(context))" href="javascript:void(0);"></a>
<a class="oi oi-x" @onclick="@(() => Delete(context as WeatherForecast))" href="javascript:void(0);"></a>
</CellTemplate>
</DxDataGridCommandColumn>
<DxDataGridColumn Field=@nameof(WeatherForecast.TemperatureC) Caption="Temp. (C)"></DxDataGridColumn>
<DxDataGridColumn Field=@nameof(WeatherForecast.TemperatureF) Caption="Temp. (F)"></DxDataGridColumn>
<DxDataGridComboBoxColumn Field=@nameof(WeatherForecast.Summary) Caption="Summary" Data=@summaries></DxDataGridComboBoxColumn>
<DxDataGridDateEditColumn Field=@nameof(WeatherForecast.Date) DisplayFormatString="dd/MM/yyyy"
EditFormatString="dd/MM/yyyy"></DxDataGridDateEditColumn>
</Columns>
<DetailRowTemplate Context="dataItem">
<DxDataGrid Data=@forecasts.Where(x=>x.TemperatureC==dataItem.TemperatureC) ShowFilterRow=false CssClass="MainGrid" @ref="MyGridDetail"
RowUpdating=@((updatingDataItem, newValues) => OnRowUpdating(updatingDataItem, newValues))
RowInserting=@((newValues) => OnRowInserting(newValues))>
<DxDataGridCommandColumn>
<HeaderCellTemplate>
<a class="oi oi-plus" @onclick="@(() => MyGridDetail.StartRowEdit(null))" href="javascript:void(0);"></a>
</HeaderCellTemplate>
<CellTemplate>
<a class="oi oi-pencil" @onclick="@(() => MyGridDetail.StartRowEdit(context))" href="javascript:void(0);"></a>
<a class="oi oi-x" @onclick="@(() => Delete(context as WeatherForecast))" href="javascript:void(0);"></a>
</CellTemplate>
</DxDataGridCommandColumn>
<DxDataGridColumn Field=@nameof(WeatherForecast.TemperatureC) Caption="Temp. (C)"></DxDataGridColumn>
<DxDataGridColumn Field=@nameof(WeatherForecast.TemperatureF) Caption="Temp. (F)"></DxDataGridColumn>
<DxDataGridComboBoxColumn Field=@nameof(WeatherForecast.Summary) Caption="Summary" Data=@summaries></DxDataGridComboBoxColumn>
<DxDataGridDateEditColumn Field=@nameof(WeatherForecast.Date) DisplayFormatString="dd/MM/yyyy"
EditFormatString="dd/MM/yyyy"></DxDataGridDateEditColumn>
</DxDataGrid>
</DetailRowTemplate>
</DxDataGrid>
}
@functions {
WeatherForecast[] forecasts;
string[] summaries;
DevExpress.Blazor.DxDataGrid<WeatherForecast> MyGrid;
DevExpress.Blazor.DxDataGrid<WeatherForecast> MyGridDetail;
protected override async Task OnInitializedAsync() {
forecasts = await ForecastService.GetForecastAsync();
summaries = await ForecastService.GetSummariesAsync();
}
async void OnRowUpdating(WeatherForecast dataItem, Dictionary<string, object> newValue) {
forecasts = await ForecastService.Update(dataItem, newValue);
}
async void OnRowInserting(Dictionary<string, object> newValue) {
forecasts = await ForecastService.Insert(newValue);
}
async void Delete(WeatherForecast item) {
if (item != null) {
forecasts = await ForecastService.Remove(item);
}
}
}
UPDATE 正如 devexpress 的 Paul V 建议的那样,我们必须创建一个新的 razor 组件来实现一个新的 DXDatagrid 组件实例,因为它不适合引用该组件,2或在同一个剃须刀组件上多次。因此,要解决此问题,请创建另一个组件(即 DetaiGrid)并在 DetailRowTemplate 中引用它并发送一个参数、主记录和详细信息源:
<DetailRowTemplate Context="dataItem">
<DetailGrid MasterRecord="@dataItem" ForecastService="@ForecastService" Forecasts="@forecasts" ></DetailGrid>
</DetailRowTemplate>
详细示例:
<h3>DetailGrid2</h3>
@using CommandButtonsWithIcons.Data
<DxDataGrid Data=@Forecasts.Where(x=>x.TemperatureC==MasterRecord.TemperatureC) ShowFilterRow=false CssClass="MainGrid" @ref="MyGridDetail"
RowUpdatingAsync=@(OnRowUpdating)
RowInsertingAsync=@(OnRowInserting)>
<DxDataGridCommandColumn>
<HeaderCellTemplate>
<a class="oi oi-plus" @onclick="@(() => MyGridDetail.StartRowEdit(null))" href="javascript:void(0);"></a>
</HeaderCellTemplate>
<CellTemplate>
<a class="oi oi-pencil" @onclick="@(() => MyGridDetail.StartRowEdit(context))" href="javascript:void(0);"></a>
</CellTemplate>
</DxDataGridCommandColumn>
<DxDataGridColumn Field=@nameof(WeatherForecast.TemperatureC) Caption="Temp. (C)"></DxDataGridColumn>
<DxDataGridColumn Field=@nameof(WeatherForecast.TemperatureF) Caption="Temp. (F)"></DxDataGridColumn>
<DxDataGridDateEditColumn Field=@nameof(WeatherForecast.Date) DisplayFormatString="dd/MM/yyyy"
EditFormatString="dd/MM/yyyy"></DxDataGridDateEditColumn>
</DxDataGrid>
@code {
[Parameter]
public WeatherForecast[] Forecasts { get; set; }
[Parameter]
public WeatherForecast MasterRecord{ get; set; }
[Parameter]
public WeatherForecastService ForecastService { get; set; }
DevExpress.Blazor.DxDataGrid<WeatherForecast> MyGridDetail = null;
async Task OnRowUpdating(WeatherForecast dataItem, IDictionary<string, object> newValue)
{
Forecasts = await ForecastService.Update(dataItem, newValue);
}
async Task OnRowInserting(IDictionary<string, object> newValue)
{
//forecasts = await ForecastService.Insert(newValue);
}
}
我不建议对多个实例使用一个 ref 变量。它可能会导致此类碰撞。将您的详细信息网格隔离在单独的组件中以解决该问题。