WPF ListView实现拖拽调整顺序

        在学习过程中,做了个Demo,分享一下,做的比较粗糙,若有不对希望哥哥们指出来
首先说说前台样式:

        
            

                
            
        
        
            
                
                    
                        
                            
                        
                        
                            
                            
                            
                        
                        
                        
                        
                        
                        
                    
                
            
            
                
            
        

        样式比较简单主要就是两个控件listview和Popup ,这个Popup主要是用来实时显示当前操作的item放在哪里了,粗线表示放在哪个地方,这是效果图:

WPF ListView实现拖拽调整顺序_第1张图片

后台主要就是拖拽的事件,不算复杂,相关的属性,方法都在下面了,可以直接用

        #region Property
        Grid lastUnderLine;
        Grid lastTopLine;
        bool isMovingUpward;
        // 声明全局变量保存拖动开始的位置
        private Point dragStartPosition;
        DataObject lastData = null;
        Stopwatch stopWatch = new Stopwatch();
        delegate Point GetPositionDelegate(IInputElement element);
        #endregion Property

        #region DropEvent
        private void ListItem_DragOver(object sender, DragEventArgs e)
        {

            myPopup.IsOpen = true;
            if (!myPopup.IsOpen)
            {
                myPopup.IsOpen = true;
            }

            Size popupSize = new Size(100, 32);
            var popupPoint = e.GetPosition(ListDemo);
            popupPoint.X += 20;             // 显示Popup的位置离鼠标X方向偏移50
            myPopup.PlacementRectangle = new Rect(popupPoint, popupSize);


        }
        // 拖动开始时的事件处理程序
        private void ListItem_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            // 记录拖动开始的位置
            dragStartPosition = e.GetPosition(ListDemo);
        }

        // 拖动进入时的事件处理程序
        private void ListItem_DragEnter(object sender, DragEventArgs e)
        {

            // 先将所有分割线不可见
            if (lastUnderLine != null)
            {
                lastUnderLine.Visibility = Visibility.Collapsed;
            }
            if (lastTopLine != null)
            {
                lastTopLine.Visibility = Visibility.Collapsed;
            }

            // 获取当前鼠标位置
            Point currentMousePosition = e.GetPosition(ListDemo);
            // 再将拖拽所在的分割线可见

            var row = GetListViewItemFromPoint(ListDemo, currentMousePosition);

            // 判断鼠标相对于拖动开始的位置是向上还是向下
            isMovingUpward = currentMousePosition.Y < dragStartPosition.Y;

            // 根据方向显示相应的分割线
            if (isMovingUpward)
            {
                // 向上移动,显示 topLine
                if (row != null)
                {
                    Grid topLine = FindVisualChild(row, "topLine");
                    topLine.Visibility = Visibility.Visible;
                    lastTopLine = topLine;

                }
            }
            else
            {
                // 向下移动,显示 underLine
                if (row != null)
                {
                    Grid underLine = FindVisualChild(row, "underLine");
                    underLine.Visibility = Visibility.Visible;
                    lastUnderLine = underLine;
                }
            }

        }
        //监测鼠标事件
        private void ListItem_MouseMove(object sender, MouseEventArgs e)
        {

            try
            {

                ListView listview = sender as ListView;

                if (e.LeftButton == MouseButtonState.Pressed)
                {
                    System.Collections.IList list = listview.SelectedItems as System.Collections.IList;
                    DataObject data = new DataObject(typeof(System.Collections.IList), list);
                    if (list.Count > 0 && lastData != data)
                    {
                        lastData = data;
                        DragDrop.DoDragDrop(listview, data, DragDropEffects.Move);
                    }
                }
                if ((e.LeftButton == MouseButtonState.Released && ListDemo.SelectedItems.Count > 0) || (stopWatch.ElapsedMilliseconds > 5000 && ListDemo.SelectedItems.Count > 0))//鼠标离开释放Drop锁定 & 未锁定情况下不释放
                {
                    stopWatch.Stop();
                    ListDemo.SelectedItems.Clear();
                }
            }
            catch (Exception)
            {
            }
        }
        //拖动完成事件
        private void ListItem__Drop(object sender, DragEventArgs e)
        {
            try
            {
                List LevelsTemp = new List();
                if (e.Data.GetDataPresent(typeof(System.Collections.IList)))
                {
                    System.Collections.IList peopleList = e.Data.GetData(typeof(System.Collections.IList)) as System.Collections.IList;
                    //index为放置时鼠标下元素项的索引  
                    int newIndex = GetCurrentIndex(new GetPositionDelegate(e.GetPosition));
                    ListDemo old = peopleList[0] as ListDemo;
                    int oldIndex = old.Index;
                    LevelsTemp = new List();
                    foreach (var item in this._page1Vm.ListDemos)
                    {
                        ListDemo levelConfig = new ListDemo()
                        {
                            Index = item.Index,
                            Name = item.Name,
                            Descripton = item.Descripton,
                        };

                        if (item.Index == oldIndex)
                        {
                            levelConfig.Index = newIndex;
                        }
                        else if (oldIndex > newIndex && item.Index >= newIndex && item.Index < oldIndex)
                        {
                            levelConfig.Index = item.Index + 1;
                        }
                        else if (oldIndex < newIndex && item.Index > oldIndex && item.Index <= newIndex)
                        {
                            levelConfig.Index = item.Index - 1;
                        }

                        LevelsTemp.Add(levelConfig);
                    }

                    LevelsTemp.Sort((x, y) => x.Index.CompareTo(y.Index));
                    this._page1Vm.ListDemos = LevelsTemp;
                }
                // 先将所有分割线不可见
                if (lastUnderLine != null)
                {
                    lastUnderLine.Visibility = Visibility.Collapsed;
                }
                if (lastTopLine != null)
                {
                    lastTopLine.Visibility = Visibility.Collapsed;
                }

                myPopup.IsOpen = false;

            }
            catch (Exception) { }
            finally
            {
                stopWatch.Stop();
            }
        }
        #endregion DropEvent

        #region Tool Method
        private ListViewItem GetListViewItemFromPoint(ListView listView, Point point)
        {
            // 使用 HitTest 获取鼠标点击位置的 HitTestResult
            HitTestResult hitTestResult = VisualTreeHelper.HitTest(listView, point);

            if (hitTestResult != null)
            {
                // 获取 HitTestResult 的 VisualHit(也就是命中的可视元素)
                DependencyObject target = hitTestResult.VisualHit;

                // 在 Visual 树中向上查找
                while (target != null && !(target is ListViewItem))
                {
                    target = VisualTreeHelper.GetParent(target);
                }
                return target as ListViewItem;
            }

            return null;
        }
        // 在 视觉树中查找具有特定类型和名称的子元素
        private T FindVisualChild(DependencyObject parent, string name) where T : DependencyObject
        {
            int count = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < count; i++)
            {
                var child = VisualTreeHelper.GetChild(parent, i);

                if (child is T typedChild && (child as FrameworkElement)?.Name == name)
                {
                    return typedChild;
                }

                var result = FindVisualChild(child, name);
                if (result != null)
                    return result;
            }

            return null;
        }





        ListViewItem GetListViewItem(int index)
        {
            if (ListDemo.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated)
                return null;
            return ListDemo.ItemContainerGenerator.ContainerFromIndex(index) as ListViewItem;
        }
        private bool IsMouseOverTarget(Visual target, GetPositionDelegate getPosition)
        {
            Rect bounds = VisualTreeHelper.GetDescendantBounds(target);
            Point mousePos = getPosition((IInputElement)target);
            return bounds.Contains(mousePos);
        }
        private int GetCurrentIndex(GetPositionDelegate getPosition)
        {
            int index = -1;
            for (int i = 0; i < ListDemo.Items.Count; ++i)
            {
                ListViewItem item = GetListViewItem(i);
                if (item != null && this.IsMouseOverTarget(item, getPosition))
                {
                    ListDemo recipeLevel = item.DataContext as ListDemo;
                    if (recipeLevel != null)
                    {
                        index = recipeLevel.Index;
                        break;
                    }
                }
            }
            return index;
        }
        #endregion

写的比较粗糙,就是一个简单的底子(拓展性强),需要拓展的哥哥们可以自己加一下动画或者样式调整一下,有问题可以私信或者评论区,看到就会回

WPF ListView实现拖拽调整顺序_第2张图片

你可能感兴趣的:(wpf)