WPF DataGrid转换器生成计算列的排序功能实现咨询
解决WPF DataGrid中转换器计算列的排序问题
首先得明确:SortMemberPath不支持绑定转换器,它本质是一个字符串属性,用来指定数据源实体的属性名称,所以你之前尝试给它绑定转换器的做法根本不会生效——这就是你的PackVolumeSortConverter从未被调用的原因。
不用扩展packs实体类,我们可以通过自定义排序逻辑+复用现有体积转换器来实现需求,具体步骤如下:
步骤1:调整体积列的XAML定义
把原来的DataGridTextColumn改成DataGridTemplateColumn,这样依然可以用你的PackVolumeConverter显示计算后的体积,同时保留排序开关:
<DataGrid x:Name="furniturePackagesGrid" ItemsSource="{Binding Path=Packs}" Sorting="furniturePackagesGrid_Sorting"> <!-- 新增排序事件绑定 --> <DataGrid.Columns> <DataGridTextColumn Header="Length" Binding="{Binding length}"/> <DataGridTextColumn Header="Width" Binding="{Binding width}" /> <DataGridTextColumn Header="Depth" Binding="{Binding depth}"/> <!-- 替换为TemplateColumn --> <DataGridTemplateColumn Header="Volume (m3)" IsReadOnly="True" CanUserSort="True"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding Converter={StaticResource PackVolumeConverter}}" /> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid>
步骤2:实现自定义排序逻辑
在View的后台代码中处理Sorting事件,复用你的PackVolumeConverter计算体积,然后通过自定义比较器完成排序:
private void furniturePackagesGrid_Sorting(object sender, DataGridSortingEventArgs e) { // 只处理体积列的排序请求 if (e.Column.Header.ToString() != "Volume (m3)") return; e.Handled = true; // 阻止DataGrid的默认排序行为 var currentSortDir = e.Column.SortDirection ?? ListSortDirection.Ascending; var targetSortDir = currentSortDir == ListSortDirection.Ascending ? ListSortDirection.Descending : ListSortDirection.Ascending; // 获取数据视图并设置自定义排序 var dataView = CollectionViewSource.GetDefaultView(furniturePackagesGrid.ItemsSource); dataView.SortDescriptions.Clear(); dataView.CustomSort = new VolumeComparer(targetSortDir); // 更新列头的排序箭头显示 e.Column.SortDirection = targetSortDir; } // 自定义比较器,复用PackVolumeConverter计算体积 private class VolumeComparer : IComparer { private readonly ListSortDirection _sortDirection; private readonly PackVolumeConverter _volumeConverter = new PackVolumeConverter(); public VolumeComparer(ListSortDirection sortDirection) { _sortDirection = sortDirection; } public int Compare(object x, object y) { var packX = x as packs; var packY = y as packs; if (packX == null || packY == null) return 0; // 用现有转换器计算两个包的体积 decimal volumeX = (decimal)_volumeConverter.Convert(packX, typeof(decimal), null, CultureInfo.CurrentCulture); decimal volumeY = (decimal)_volumeConverter.Convert(packY, typeof(decimal), null, CultureInfo.CurrentCulture); // 根据排序方向返回比较结果 int compareResult = volumeX.CompareTo(volumeY); return _sortDirection == ListSortDirection.Descending ? -compareResult : compareResult; } }
为什么这个方案可行?
- 完全不需要修改
packs实体类,复用了你已经写好的PackVolumeConverter,避免代码冗余; - 通过拦截
Sorting事件,替换成我们自己的排序逻辑,绕开了SortMemberPath只能绑定实体属性的限制; - 自定义比较器直接使用转换器计算体积,保证排序逻辑和显示逻辑的一致性。
内容的提问来源于stack exchange,提问作者Andrew Miller
相关产品推荐
相关产品推荐

