简体   繁体   English

在WPF(C#)中的两个Datagrid之间拖放

[英]Drag and Drop between two Datagrid in WPF (C#)

Sorry for my English, this is not my native language. 对不起,我的英语,这不是我的母语。 Please tell me if you don't understand something. 如果您听不懂,请告诉我。

I'm starting C# and WPF, and I need to implement a drag and drop functionality between two datagrid. 我正在启动C#和WPF,并且需要实现两个数据网格之间的拖放功能。 I already searched a lot but I don't find anything that helps me. 我已经搜索了很多东西,但是找不到任何可以帮助我的东西。 It always shows how to do drag and drop between two different controls, or only in the same datagrid, and I'm not able to adapt these answers to my need because I don't understand some parts of the solutions. 它总是显示如何在两个不同的控件之间或仅在同一数据网格中进行拖放,并且由于我不了解解决方案的某些部分,因此我无法适应这些答案。 So I came here to ask a really precise question : How to implement drag and drop between two datagrids ? 因此,我来​​这里提出一个非常精确的问题:如何在两个数据网格之间实现拖放?

I would be very grateful if you could help me. 如果您能帮助我,我将不胜感激。

this a sample code ( More Details here ) 这是一个示例代码( 此处有更多详细信息

  1. Define MouseDown Event 定义MouseDown事件
  2. Define MouseMove Event to start DragAndDrop operation 定义MouseMove事件以启动DragAndDrop操作
  3. Define DragOver to test if drop allowed or not 定义DragOver以测试是否允许放置
  4. Define Drop event to do the drop operation 定义Drop事件以执行放置操作

You can use the same event for the two datagrid 您可以对两个数据网格使用相同的事件

    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;
    }

Hope this help :) 希望这个帮助:)

for that you need two Datagrid feed list or observableCollection like this in xaml: 为此,您需要在xaml中使用两个这样的Datagrid feed列表或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>

I let you insert the source of Datagrid with : 我让您插入Datagrid的源:

dg1.ItemSource = "yourlist1";

dg2.ItemSource = "yourlist2";

Once the source fill in the datagrid add this to the top of your code c#: 将源代码填充到datagrid中后,将其添加到代码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);
        }

Then add all this after the MainWindow : 然后在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;
        }

All you have to do is replace the "dg1" and "dg2" by the names of your Datagrid and the "yourlist1" and "yourlist2" by the lists that feed your Datagrid. 您要做的就是用Datagrid的名称替换“ dg1”和“ dg2”,并用提供给Datagrid的列表替换“ yourlist1”和“ yourlist2”。

Please excuse me too for my English because I do not speak it at all, and I was inspired by Raj Kumar's article : https://www.c-sharpcorner.com/UploadFile/raj1979/drag-and-drop-datagrid-row-in-wpf/ 也请为我的英语打个招呼,因为我一点都不讲,而且我受到拉杰·库马尔的文章的启发: https : //www.c-sharpcorner.com/UploadFile/raj1979/drag-and-drop-datagrid-row -in-WPF /

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM