在WPF (c#)中拖放两个数据网格

本文关键字:数据 两个 数据网 网格 拖放 WPF | 更新日期: 2023-09-27 18:11:26

对不起,我的英语不是我的母语。如果有什么不明白的地方请告诉我。

我开始使用c#和WPF,我需要在两个数据网格之间实现拖放功能。我已经找了很多,但没有找到任何有用的东西。它总是显示如何在两个不同的控件之间进行拖放,或者仅在相同的数据网格中进行拖放,我无法根据我的需要调整这些答案,因为我不理解解决方案的某些部分。所以我来这里问一个非常精确的问题:如何实现两个数据网格之间的拖放?

如果你能帮助我,我将非常感激。

在WPF (c#)中拖放两个数据网格

这是一个示例代码(更多细节在这里)

  1. 定义MouseDown事件
  2. 定义鼠标移动事件来启动拖放操作
  3. 定义拖放来测试是否允许拖放
  4. 定义Drop事件来执行Drop操作

您可以为两个数据网格使用相同的事件

    private Point? _startPoint;
    private void dataGrid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        _startPoint = e.GetPosition(null);
    }
    private void dataGrid_PreviewMouseMove(object sender, MouseEventArgs e)
    {
        // No drag operation
        if (_startPoint == null)
            return;
        var dg = sender as DataGrid;
        if (dg == null) return; 
        // Get the current mouse position
        Point mousePos = e.GetPosition(null);
        Vector diff = _startPoint.Value - mousePos;
        // test for the minimum displacement to begin the drag
        if (e.LeftButton == MouseButtonState.Pressed &&
            (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
            Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
        {
            // Get the dragged DataGridRow
            var DataGridRow=
                FindAnchestor<DataGridRow>((DependencyObject)e.OriginalSource);
            if (DataGridRow == null)
                return;
            // Find the data behind the DataGridRow
            var dataTodrop = (DataModel)dg.ItemContainerGenerator.
                ItemFromContainer(DataGridRow);
            if (dataTodrop == null) return;
            // Initialize the drag & drop operation
            var dataObj = new DataObject(dataTodrop);
            dataObj.SetData("DragSource", sender);
            DragDrop.DoDragDrop(dg, dataObj, DragDropEffects.Copy);
            _startPoint = null;
        }
    }
    private void dataGrid_PreviewMouseUp(object sender, MouseButtonEventArgs e)
    {
        _startPoint = null;
    }
    private void dataGrid_Drop(object sender, DragEventArgs e)
    {
        var dg = sender as DataGrid;
        if (dg == null) return;
        var dgSrc = e.Data.GetData("DragSource") as DataGrid;
        var data = e.Data.GetData(typeof(DataModel));
        if (dgSrc == null || data == null) return;
        // Implement move data here, depends on your implementation
        MoveDataFromSrcToDest(dgSrc, dg, data);
        // OR
        MoveDataFromSrcToDest(dgSrc.DataContext, dg.DataContext, data);
    }
    private void dataGrid_PreviewDragOver(object sender, DragEventArgs e)
    {
         // TO test if drop is allowed, to avoid drop 
         // if false e.Effects = DragDropEffects.None;
    }

    // Helper to search up the VisualTree
    private static T FindAnchestor<T>(DependencyObject current)
        where T : DependencyObject
    {
        do
        {
            if (current is T)
            {
                return (T)current;
            }
            current = VisualTreeHelper.GetParent(current);
        }
        while (current != null);
        return null;
    }

希望有帮助

为此,您需要两个Datagrid提要列表或像xaml:

这样的observableCollection。
<DataGrid AllowDrop="True" Name="dg1" Margin="10,50,10,30" Grid.Column="1">
    //Set your column and what you want
</DataGrid>
<DataGrid Name="dg2" AllowDrop="True" Margin="10,50,10,30" Grid.Column="2">
    //Set your column and what you want
</DataGrid>

我让你插入Datagrid的来源:

dg1.ItemSource = "yourlist1";

dg2.ItemSource = "yourlist2";

一旦源代码填入数据网格,将其添加到代码的顶部c#:

namespace YourAppName
{
    public partial class MainWindow : Window
    {
        public delegate Point GetPosition(IInputElement element);
        int rowIndex = -1;
        string dgName;
        public MainWindow()
        {
            dg1.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(DgSupp_PreviewMouseLeftButtonDown);
            dg1.Drop += new DragEventHandler(Dg_Drop);
            dg2.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(DgSupp_PreviewMouseLeftButtonDown);
            dg2.Drop += new DragEventHandler(Dg_Drop);
        }

然后将所有这些添加到MainWindow后面:

void Dg_Drop(object sender, DragEventArgs e)
        {
            int index = -1;
            DataGrid dg = new DataGrid();
            if (sender is DataGrid)
            {
                dg = (DataGrid)sender;
            }
            if (rowIndex < 0)
                return;
            if (dg.Name == "dg1")
            {
                index = this.GetCurrentRowIndexSupp(e.GetPosition);
            }
            if (dg.Name == "dg2")
            {
                index = this.GetCurrentRowIndexAdd(e.GetPosition);
            }
            if (index < 0)
                return;
            if (index == rowIndex)
                return;
            if (index == dg.Items.Count - 1)
            {
                MessageBox.Show("Last line can't moove");
                return;
            }
            if (dg.Name == "dg1")
            {
                if (dgName == "dg2")
                {
                    DataOfGrid changedProduct = yourlist2[rowIndex];
                    yourlist2.RemoveAt(rowIndex);
                    yourlist1.Insert(index, changedProduct);
                }
                else
                {
                    DataOfGrid changedProduct = yourlist1[rowIndex];
                    yourlist1.RemoveAt(rowIndex);
                    yourlist1.Insert(index, changedProduct);
                }
            }
            if (dg.Name == "dg2")
            {
                if (dgName == "dg1")
                {
                    DataOfGrid changedProduct = yourlist1[rowIndex];
                    yourlist1.RemoveAt(rowIndex);
                    yourlist2.Insert(index, changedProduct);
                }
                else
                {
                    DataOfGrid changedProduct = yourlist2[rowIndex];
                    yourlist2.RemoveAt(rowIndex);
                    yourlist2.Insert(index, changedProduct);
                }
            }
            dg1.ItemsSource = yourlist1;
            dg1.Items.Refresh();
            dg2.ItemsSource = yourlist2;
            dg2.Items.Refresh();
        }
        void DgSupp_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            DataGrid dg = new DataGrid();
            if (sender is DataGrid)
            {
                dg = (DataGrid)sender;
            }
            if (dg.Name == "dg1")
            {
                rowIndex = GetCurrentRowIndexSupp(e.GetPosition);
                dgName = dg.Name;
            }
            if (dg.Name == "dg2")
            {
                rowIndex = GetCurrentRowIndexAdd(e.GetPosition);
                dgName = dg.Name;
            }
            if (rowIndex < 0)
                return;
            dg.SelectedIndex = rowIndex;
            DataOfGrid selectedEmp = dg.Items[rowIndex] as DataOfGrid;
            if (selectedEmp == null)
                return;
            DragDropEffects dragdropeffects = DragDropEffects.Move;
            if (DragDrop.DoDragDrop(dg, selectedEmp, dragdropeffects)
                                != DragDropEffects.None)
            {
                dg.SelectedItem = selectedEmp;
            }
        }
        private bool GetMouseTargetRow(Visual theTarget, GetPosition position)
        {
            Rect rect = VisualTreeHelper.GetDescendantBounds(theTarget);
            Point point = position((IInputElement)theTarget);
            return rect.Contains(point);
        }
        private DataGridRow GetRowItemList1(int index)
        {
            if (dg1.ItemContainerGenerator.Status
                    != GeneratorStatus.ContainersGenerated)
                return null;
            return dg1.ItemContainerGenerator.ContainerFromIndex(index) as DataGridRow;
        }
        private DataGridRow GetRowItemList2(int index)
        {
            if (dg2.ItemContainerGenerator.Status
                    != GeneratorStatus.ContainersGenerated)
                return null;
            return dg2.ItemContainerGenerator.ContainerFromIndex(index) as DataGridRow;
        }
        private int GetCurrentRowIndexSupp(GetPosition pos)
        {
            int curIndex = -1;
            for (int i = 0; i < dg1.Items.Count; i++)
            {
                DataGridRow itm = GetRowItemList1(i);
                if (GetMouseTargetRow(itm, pos))
                {
                    curIndex = i;
                    break;
                }
            }
            return curIndex;
        }
        private int GetCurrentRowIndexAdd(GetPosition pos)
        {
            int curIndex = -1;
            for (int i = 0; i < dg2.Items.Count; i++)
            {
                DataGridRow itm = GetRowItemList2(i);
                if (GetMouseTargetRow(itm, pos))
                {
                    curIndex = i;
                    break;
                }
            }
            return curIndex;
        }

你所要做的就是把"dg1"answers"dg2"替换为你的Datagrid的名称,把"yourlist1"answers"yourlist2"替换为你的Datagrid的列表。

也请原谅我的英语,因为我根本不会说,我的灵感来自Raj Kumar的文章:https://www.c-sharpcorner.com/UploadFile/raj1979/drag-and-drop-datagrid-row-in-wpf/