You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:55:46