如何阻止行点击触发DetailRow显隐,仅按指定条件展示DetailRow
解决方案:仅通过行数据状态控制DataGrid DetailRow显示
核心问题分析
你遇到的问题根源在于:
- 全局给所有列加
PreventRowClick会完全阻断行级交互,导致DetailRowTrigger的评估逻辑无法被触发 - 默认情况下DataGrid会把行点击作为DetailRow显示/隐藏的触发源,即使指定了
DetailRowTrigger,行点击仍会覆盖自定义逻辑
具体修复步骤
1. 禁用行点击的默认DetailRow切换行为
在DataGrid组件上添加RowClickMode="DataGridRowClickMode.None",彻底取消行点击对DetailRow的控制:
<DataGrid TItem="VisitDocumentDTO" Data="@VisitDocuments" @ref="dataGridRef" RowStyling="@OnRowStyling" Responsive Resizable ResizeMode="TableResizeMode.Header" SortMode="DataGridSortMode.Single" ShowPager ShowPageSizes ShowGrouping CustomFilter="@OnCustomFilter" DetailRowStartsVisible="true" DetailRowTrigger="@ShowDetailRow" RowClickMode="DataGridRowClickMode.None" <!-- 新增该行 --> PagerPosition="DataGridPagerPosition.Bottom" PagerOptions="new(){ ButtonSize=Size.Small }">
2. 移除所有列的PreventRowClick属性
不需要再给每个列单独添加PreventRowClick,已经通过RowClickMode禁用了行点击的默认行为,保留列的正常交互能力。
3. 确保ShowDetailRow直接基于行数据状态判断
你的ShowDetailRow方法需要直接返回行的BillingStatus或预览状态,示例如下:
// 假设用字典跟踪各行的预览状态 private Dictionary<int, bool> _previewStates = new(); private bool ShowDetailRow(VisitDocumentDTO row) { var isPreviewActive = _previewStates.TryGetValue(row.Id, out var state) && state; return row.BillingStatus || isPreviewActive; }
4. 状态变更时强制重新评估DetailRow
在BillingStatus切换和预览按钮点击时,需要通知组件重新渲染,确保DetailRowTrigger被重新计算:
- 修改Switch的CheckedChanged事件:
<Switch TValue="bool" Checked="@context.BillingStatus" CheckedChanged="@( (va) => { context.BillingStatus = va; StateHasChanged(); // 通知组件重新渲染 })"> Billable </Switch>
- 修改Preview按钮的点击事件:
private void TogglePreviewState(VisitDocumentDTO row) { if (_previewStates.ContainsKey(row.Id)) _previewStates[row.Id] = !_previewStates[row.Id]; else _previewStates[row.Id] = true; StateHasChanged(); // 触发重新评估DetailRowTrigger }
5. 可选:让DTO实现INotifyPropertyChanged(更优雅的状态通知)
如果你的VisitDocumentDTO实现了INotifyPropertyChanged,修改BillingStatus时会自动触发通知,无需手动调用StateHasChanged():
public class VisitDocumentDTO : INotifyPropertyChanged { private bool _billingStatus; public bool BillingStatus { get => _billingStatus; set { if (_billingStatus != value) { _billingStatus = value; OnPropertyChanged(); } } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } // 其他属性... }
最终效果
完成以上修改后,DetailRow的显示将完全由以下两个条件控制:
- 行的
BillingStatus为true - 该行的预览状态被激活
行点击不会再影响DetailRow的显示,同时DetailRowTrigger会在状态变更时自动重新评估。
内容的提问来源于stack exchange,提问作者Jon Hogan-Doran
相关产品推荐
相关产品推荐

