【问题标题】:Drag and Drop between two Datagrid in WPF (C#)在 WPF 中的两个 Datagrid 之间拖放(C#)
【发布时间】:2015-09-07 10:03:18
【问题描述】:

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

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

如果你能帮助我,我将不胜感激。

【问题讨论】:

    标签: c# wpf datagrid drag-and-drop


    【解决方案1】:

    这是一个示例代码 (More Details here)

    1. 定义 MouseDown 事件
    2. 定义 MouseMove 事件以启动 DragAndDrop 操作
    3. 定义 DragOver 以测试是否允许放置
    4. 定义 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;
        }
    

    希望得到帮助:)

    【讨论】:

    • 我已经尝试过这个网站上的内容,但我失败了。这个例子是用 ListView 制作的,而不是 Datagrid。我再试一次,但我不认为我会成功......
    • 我做的例子是使用datagrid,我试过了,它可以工作。以上链接仅供参考
    • 很抱歉,您只是摘录了您发送的链接中的内容。谢谢你的代码。我试过了,但我认为缺少某些部分(“listViewItem”是未知的,我不知道要导入什么才能使用 DataModel 类型)
    • 我编辑代码,listwiewItem 不应该在那里:)。因为 DataModel 是我用来存储虚构数据 (List) 以测试代码的类。您必须将存储数据的类显示在数据网格中。
    【解决方案2】:

    为此,您需要两个 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”和“dg2”替换为 Datagrid 的名称,将“yourlist1”和“yourlist2”替换为为 Datagrid 提供数据的列表。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多