WPF DataGrid虚拟化导致Expander图标与展开状态不一致的解决办法
WPF DataGrid虚拟化下自定义Expander状态不一致问题解决
问题
DataGrid启用行虚拟化时,自定义Expander点击展开后图标变为-,但滚动后图标变回+,而RowDetails仍保持展开状态。关闭虚拟化会导致数千行数据的性能问题,需要兼顾性能和状态一致性的方案。
原因
DataGrid虚拟化会回收不可见的行,Expander的IsExpanded状态仅存储在UI元素中,行被回收后状态丢失;而RowDetails的Visibility是通过后台代码手动设置的,和Expander状态没有绑定,导致两者脱节。
解决方案
将Expander的展开状态与数据模型绑定,让UI状态依赖于数据而非临时的UI元素状态,彻底解决虚拟化回收带来的状态丢失问题。
1. 扩展数据模型
给数据实体(如Patient类)添加IsDetailsExpanded属性并实现INotifyPropertyChanged:
public class Patient : INotifyPropertyChanged { // 原有属性:FirstName, LastName, Total... private bool _isDetailsExpanded; public bool IsDetailsExpanded { get => _isDetailsExpanded; set { if (_isDetailsExpanded != value) { _isDetailsExpanded = value; OnPropertyChanged(nameof(IsDetailsExpanded)); } } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
2. 修改XAML绑定
添加转换器资源
在UserControl.Resources中添加布尔值转可见性的转换器:
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
绑定DataGridRow的DetailsVisibility
修改DataGridRow的Style,将DetailsVisibility绑定到数据模型的属性:
<Style TargetType="{x:Type DataGridRow}"> <Setter Property="Template"> <!-- 原有Template内容保持不变 --> </Setter> <Setter Property="DetailsVisibility" Value="{Binding IsDetailsExpanded, Converter={StaticResource BooleanToVisibilityConverter}}"/> </Style>
绑定Expander的IsExpanded
移除Expander的事件处理,双向绑定到数据模型属性:
<DataGridTemplateColumn Width="Auto"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <Expander Template="{StaticResource SimpleExpanderTemp}" IsExpanded="{Binding IsDetailsExpanded, Mode=TwoWay}"/> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn>
3. 移除后台事件代码
删除后台的Expander_Expanded和Expander_Collapsed方法,状态同步完全通过绑定实现:
public partial class OutstandingPatientDataGrid : UserControl { public OutstandingPatientDataGrid() { InitializeComponent(); } // 移除两个事件处理方法 }
效果说明
- 点击Expander时,
IsDetailsExpanded属性更新,同步RowDetails的显示状态 - 行被虚拟化回收后,复用行时会从数据模型读取
IsDetailsExpanded值,自动同步Expander图标和RowDetails状态 - 保持虚拟化开启,确保大数据量下的性能
内容的提问来源于stack exchange,提问作者May Nguyen
相关产品推荐
相关产品推荐

