DataGrid 拖动 附加属性类

项目需要实现一个DataGrid拖动排序,于是参考网上一些资源然后,修改了下实现了一个附加属性类,如下

使用方法

<DataGrid
            x:Name="shareGrid"
            test:DragDropRowBehavior.Enabled="True"
            test:DragDropRowBehavior.DropFinish="{Binding TestCommand}" />

DropFinish有在鼠标释放时调用,参数中包含了 拖动的数据,行号,目标行号,目标数据等。

 

 

源码:

  public static class DataGridDragDropRowBehavior
    {
        public delegate Point GetDragDropPosition(IInputElement theElement);

        public static DependencyProperty DropFinishProperty =
       DependencyProperty.RegisterAttached("DropFinish", typeof(ICommand), typeof(DataGridDragDropRowBehavior),
                                           new UIPropertyMetadata(null));

        public static void SetDropFinish(UIElement target, ICommand value)
        {
            target.SetValue(DropFinishProperty, value);
        }

        public static bool GetEnabled(DependencyObject obj)
        {
            return (bool)obj.GetValue(EnabledProperty);
        }

        public static void SetEnabled(DependencyObject obj, bool value)
        {
            obj.SetValue(EnabledProperty, value);
        }

        public static readonly DependencyProperty EnabledProperty =
            DependencyProperty.RegisterAttached("Enabled", typeof(bool), typeof(DataGridDragDropRowBehavior), new PropertyMetadata(false, OnEnableChanged));

        private static void OnEnableChanged(DependencyObject depObject, DependencyPropertyChangedEventArgs e)
        {
            var dataGrid = depObject as DataGrid;

            var enable = (bool)e.NewValue;
            if (enable)
            {
                dataGrid.AllowDrop = true;
                dataGrid.PreviewMouseLeftButtonDown += DataGrid_PreviewMouseLeftButtonDown;
                dataGrid.Drop += DataGrid_Drop;
            }
            else
            {
                dataGrid.PreviewMouseLeftButtonDown -= DataGrid_PreviewMouseLeftButtonDown;
                dataGrid.Drop -= DataGrid_Drop;
            }
        }

        private static void DataGrid_Drop(object sender, DragEventArgs e)
        {
            DragItem dragitem = e.Data.GetData("DragItem") as DragItem;

            if (dragitem.RowIndex < 0)
            {
                return;
            }
            DataGrid datagrid = sender as DataGrid;
            int index = GetDataGridItemCurrentRowIndex(e.GetPosition, datagrid);

            //The current Rowindex is -1 (No selected)
            if (index < 0)
            {
                return;
            }
            //If Drag-Drop Location are same
            if (index == dragitem.RowIndex)
            {
                return;
            }

            var targetItem = datagrid.Items[index];

            DropEventArgs arg = new DropEventArgs();
            arg.SourceRowIndex = dragitem.RowIndex;
            arg.TargetRowIndex = index;
            arg.Data = dragitem.Data;
            arg.TargetData = targetItem;

            var command = (ICommand)datagrid.GetValue(DropFinishProperty);
            if (command != null)
            {
                command.Execute(arg);
            }
        }

        private static void DataGrid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            DataGrid datagrid = sender as DataGrid;
            var m_prevRowIndex = GetDataGridItemCurrentRowIndex(e.GetPosition, datagrid);

            if (m_prevRowIndex < 0)
            {
                return;
            }
            datagrid.SelectedIndex = m_prevRowIndex;

            var selectedItem = datagrid.Items[m_prevRowIndex];

            if (selectedItem == null)
            {
                return;
            }

            DragItem dragItem = new DragItem();
            dragItem.RowIndex = m_prevRowIndex;
            dragItem.Data = selectedItem;
            DataObject data = new DataObject("DragItem", dragItem);
            //Now Create a Drag Rectangle with Mouse Drag-Effect
            //Here you can select the Effect as per your choice

            DragDropEffects dragdropeffects = DragDropEffects.Move;

            if (DragDrop.DoDragDrop(datagrid, data, dragdropeffects) != DragDropEffects.None)
            {
                //Now This Item will be dropped at new location and so the new Selected Item
                datagrid.SelectedItem = selectedItem;
            }
        }

        /// <summary>
        /// Method checks whether the mouse is on the required Target
        /// Input Parameter (1) "Visual" -> Used to provide Rendering support to WPF
        /// Input Paraneter (2) "User Defined Delegate" positioning for Operation
        /// </summary>
        /// <param name="theTarget"></param>
        /// <param name="pos"></param>
        /// <returns>The "Rect" Information for specific Position</returns>
        private static bool IsTheMouseOnTargetRow(Visual theTarget, GetDragDropPosition pos)
        {
            Rect posBounds = VisualTreeHelper.GetDescendantBounds(theTarget);
            Point theMousePos = pos((IInputElement)theTarget);
            return posBounds.Contains(theMousePos);
        }

        private static DataGridRow GetDataGridRowItem(DataGrid dataGrid, int index)
        {
            if (dataGrid.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated)
            {
                return null;
            }
            return dataGrid.ItemContainerGenerator.ContainerFromIndex(index)
                                                            as DataGridRow;
        }

        private static int GetDataGridItemCurrentRowIndex(GetDragDropPosition pos, DataGrid dataGrid)
        {
            int curIndex = -1;
            for (int i = 0; i < dataGrid.Items.Count; i++)
            {
                DataGridRow itm = GetDataGridRowItem(dataGrid, i);
                if (IsTheMouseOnTargetRow(itm, pos))
                {
                    curIndex = i;
                    break;
                }
            }
            return curIndex;
        }
    }

    public class DragItem
    {
        public int RowIndex { get; set; }
        public object Data { get; set; }
    }

    public class DropEventArgs
    {
        public int SourceRowIndex { get; set; }
        public object Data { get; set; }

        public int TargetRowIndex { get; set; }

        public object TargetData { get; set; }
    }

 

参考资源:http://www.dotnetcurry.com/wpf/677/wpf-data-grid-row-drag-drop

 

posted @ 2017-11-29 13:23  碎心炼心  阅读(602)  评论(0编辑  收藏  举报