DataGridTextColumn数值排序失败:BindingListCollectionView转IList报错
解决DataGrid数值排序的绑定类型转换错误问题
你遇到的InvalidCastException核心原因很明确:你绑定的数据源是DataView,它对应的默认视图是BindingListCollectionView,而这个类型不能直接强制转换为IList,所以new ListCollectionView((IList)...)这行代码才会抛出异常。
下面给你两种更靠谱的解决方案,从简单到灵活,按需选择:
方案一:直接利用DataView自带的排序(最简洁)
因为你的数据源是DataView,它本身就内置了排序功能,完全不需要绕到CollectionView的自定义排序,代码更简洁性能也更好:
private void dataGrid_Sorting(object sender, DataGridSortingEventArgs e) { DataGridColumn column = e.Column; string targetColumn = column.SortMemberPath; // 只处理需要数值排序的列,这里替换成你的目标列名 if (targetColumn != "id") return; e.Handled = true; // 切换排序方向 ListSortDirection direction = column.SortDirection != ListSortDirection.Ascending ? ListSortDirection.Ascending : ListSortDirection.Descending; column.SortDirection = direction; // 获取数据源并设置排序规则 var dataView = dataGrid.ItemsSource as DataView; if (dataView == null) return; // DataView的Sort属性格式为 "列名 ASC/DESC" dataView.Sort = $"{targetColumn} {(direction == ListSortDirection.Ascending ? "ASC" : "DESC")}"; }
这种方法的优势是:不需要写自定义比较器,DataView会自动按数值类型排序(前提是你的列在DataSet中是数值类型,或者DataView能识别为数值),代码量极少。
方案二:用BindingListCollectionView实现自定义排序(更灵活)
如果你的场景需要更复杂的自定义排序逻辑(比如混合数值和特殊字符处理),可以直接使用当前的BindingListCollectionView,而不是强行创建ListCollectionView:
首先定义一个数值比较器:
public class NumericalComparer : IComparer { private readonly ListSortDirection _sortDirection; public NumericalComparer(ListSortDirection sortDirection) { _sortDirection = sortDirection; } public int Compare(object x, object y) { // 转换为DataRowView(因为数据源是DataView,每行都是DataRowView) var rowX = x as DataRowView; var rowY = y as DataRowView; if (rowX == null || rowY == null) return 0; // 尝试转换为int类型,根据你的实际数值类型调整(比如long、decimal) if (int.TryParse(rowX["id"].ToString(), out int valX) && int.TryParse(rowY["id"].ToString(), out int valY)) { int comparisonResult = valX.CompareTo(valY); // 根据排序方向反转结果 return _sortDirection == ListSortDirection.Descending ? -comparisonResult : comparisonResult; } // 转换失败时 fallback 到字符串排序 return string.Compare(rowX["id"].ToString(), rowY["id"].ToString()); } }
然后修改排序事件:
private void dataGrid_Sorting(object sender, DataGridSortingEventArgs e) { DataGridColumn column = e.Column; if (column.SortMemberPath != "id") return; e.Handled = true; ListSortDirection direction = column.SortDirection != ListSortDirection.Ascending ? ListSortDirection.Ascending : ListSortDirection.Descending; column.SortDirection = direction; // 获取当前的BindingListCollectionView,不需要强制转换为IList var collectionView = CollectionViewSource.GetDefaultView(dataGrid.ItemsSource) as BindingListCollectionView; if (collectionView == null) return; // 设置自定义比较器 collectionView.CustomSort = new NumericalComparer(direction); }
关键注意点:
- 确保你要排序的列确实是数值类型,或者在比较器中处理好类型转换逻辑,避免转换失败导致的意外排序。
- 如果你用自定义列
DataChimpIntegerColumn,可以在列内部封装数值转换逻辑,让比较器更通用。
内容的提问来源于stack exchange,提问作者Jake Hayton
相关产品推荐
相关产品推荐

