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

DataGrid列排序后拖拽功能失效,需提升拖拽优先级实现共存

解决DataGrid排序后行拖拽失效的问题

问题根源

DataGrid列排序后,内部会生成排序后的ICollectionView作为实际显示数据源,而非直接使用原始的ProductCollection。若拖拽逻辑未正确处理视图与原始集合的索引映射,就会导致拖拽功能失效。

具体修复方案

1. 拖拽开始时绑定原始集合项

不要直接使用DataGrid视图的索引,转而获取原始集合中对应项的真实索引:

private Product _draggedItem;
private int _originalIndex;

private void DataGrid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    var dataGrid = sender as DataGrid;
    var row = FindVisualParent<DataGridRow>(e.OriginalSource as DependencyObject);
    if (row != null && row.IsSelected)
    {
        _draggedItem = row.Item as Product;
        // 直接从原始集合获取索引,跳过视图层
        _originalIndex = (dataGrid.ItemsSource as ProductCollection).IndexOf(_draggedItem);
    }
}

2. 放置操作直接修改原始集合

拖拽放置时直接更新原始的ProductCollection,排序后的视图会自动同步显示:

private void DataGrid_Drop(object sender, DragEventArgs e)
{
    var dataGrid = sender as DataGrid;
    var targetRow = FindVisualParent<DataGridRow>(e.OriginalSource as DependencyObject);
    if (targetRow != null && _draggedItem != null)
    {
        var targetItem = targetRow.Item as Product;
        var targetIndex = (dataGrid.ItemsSource as ProductCollection).IndexOf(targetItem);
        
        var collection = dataGrid.ItemsSource as ProductCollection;
        // 修改原始集合,视图会自动刷新排序后的显示
        collection.RemoveAt(_originalIndex);
        collection.Insert(targetIndex, _draggedItem);
        
        dataGrid.SelectedItem = _draggedItem;
        _draggedItem = null;
    }
}

3. 临时禁用视图排序(可选兜底方案)

若上述方法仍有冲突,可在拖拽过程中临时清空视图排序,拖拽结束后恢复:

private List<SortDescription> _savedSortDescriptions = new();

// 先在DataGrid排序事件中保存排序规则
private void DataGrid_Sorting(object sender, DataGridSortingEventArgs e)
{
    var view = CollectionViewSource.GetDefaultView((sender as DataGrid).ItemsSource);
    _savedSortDescriptions.Clear();
    foreach (var sort in view.SortDescriptions)
    {
        _savedSortDescriptions.Add(new SortDescription(sort.PropertyName, sort.Direction));
    }
}

// 拖拽时临时禁用排序
private void DataGrid_PreviewMouseMove(object sender, MouseEventArgs e)
{
    if (_draggedItem != null && e.LeftButton == MouseButtonState.Pressed)
    {
        var dataGrid = sender as DataGrid;
        var view = CollectionViewSource.GetDefaultView(dataGrid.ItemsSource);
        view.SortDescriptions.Clear();
        
        DragDrop.DoDragDrop(dataGrid, _draggedItem, DragDropEffects.Move);
        
        // 拖拽结束后恢复原有排序
        foreach (var sort in _savedSortDescriptions)
        {
            view.SortDescriptions.Add(sort);
        }
    }
}

4. 确保集合类接口合规

确认ProductCollection继承自ObservableCollection<Product>,该类已实现INotifyCollectionChanged和IList接口,能保证集合修改后视图自动同步:

public class ProductCollection : ObservableCollection<Product>
{
    // 保留原有业务逻辑即可
}

核心思路

让拖拽操作直接作用于原始数据集合,而非DataGrid的排序视图。ICollectionView会自动将原始集合的修改同步到排序后的显示界面,实现排序状态与拖拽功能的共存。

内容的提问来源于stack exchange,提问作者Tech_T

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 15:12:43