WPF 可拖动的ListView


这是一个很简单的程序,致力于快速打开 exe 执行文件,方便删除与新增,同时还可以拖拽 listviewitem 进行更新优先级

用途

  • 书签
  • 笔记
  • 歌单
  • 排班

支持功能

  • 批量多选
  • 打开执行程序
  • 删除列表
  • 保存状态
  • 拖动效果
  • xml 读取与更新
# 读取xml文件
        public void Read()
        {
            Task.Factory.StartNew(() =>
            {
                XmlDocument xml = new XmlDocument();
                xml.Load(Path.Combine(baseDir, "Data.xml"));
                var Item = xml.SelectSingleNode("exeTer");
                XmlNodeList node = Item.ChildNodes;
                foreach (XmlNode item in node)
                {
                    XmlElement _xml = (XmlElement)item;
                    var _path = _xml.GetAttribute("Path");
                    var _fileName = _xml.GetAttribute("FileName");
                    var _xmlmodel = new List();
                    App.Current.Dispatcher.InvokeAsync(() =>
                    {
                        ExeterItems.Add(new Exeter()
                        {
                            Path = _path,
                            FileName = _fileName,
                        });
                    });

                }
            });

        }
# 保存和更新
        private void SaveUpdate(List exeters)
        {
            List _list = new List();
            XmlDocument xml = new XmlDocument();
            var xmlpath = Path.Combine(baseDir, "Data.xml");
            xml.Load(xmlpath);
            var Item = xml.SelectSingleNode("exeTer");
            var length = Item.ChildNodes.Count;
            for (int i = length - 1; i >= 0; i--)
            {
                XmlElement _xml = (XmlElement)Item.ChildNodes[i];
                var _fileName = _xml.GetAttribute("FileName");
                var ishas = exeters.Any(p => p.FileName == _fileName);
                if (ishas)
                {
                    Item.RemoveChild(_xml);
                }
            }

            foreach (var item in exeters)
            {
                XmlElement unit = xml.CreateElement("AUnit");
                unit.SetAttribute("Path", item.Path);
                unit.SetAttribute("FileName", item.FileName);
                Item.AppendChild(unit);
            }
            xml.Save(xmlpath);
        }

在 Microsoft.Xaml.Behaviors.Wp 扩展中使用了 InvokeCommandAction

         
                
                    
                        
                    
                    
                        
                    
                
            

拖动效果

            
                
                    
                        
                            
                                
                                
                                
                            
                            
                            
        private void Exelist_DragLeave(object sender, DragEventArgs e)
        {
            if (tgBtn.IsChecked == true)
            {
                e.Effects = DragDropEffects.None;
                Point pos = e.GetPosition(exelist);
                HitTestResult result = VisualTreeHelper.HitTest(exelist, pos);
                if (result == null)
                    return;

                ListViewItem selectedItem = VisualObjectHelper.FindVisualParent(result.VisualHit);
                if (selectedItem != null)
                    selectedItem.IsSelected = false;
            }
        }
        private void Exelist_DragEnter(object sender, DragEventArgs e)
        {
            if (tgBtn.IsChecked == true)
            {
                e.Effects = DragDropEffects.Copy;

                Point pos = e.GetPosition(exelist);
                HitTestResult result = VisualTreeHelper.HitTest(exelist, pos);
                if (result == null)
                    return;

                ListViewItem selectedItem = VisualObjectHelper.FindVisualParent(result.VisualHit);
                if (selectedItem != null)
                    selectedItem.IsSelected = true;
            }

        }
# 持续拖动,不停的更新
        private void Exelist_QueryContinueDrag(object sender, QueryContinueDragEventArgs e)
        {
            if (mAdornerLayer == null)
                return;

            System.Diagnostics.Debug.WriteLine($"Exelist_QueryContinueDrag {DateTime.Now.ToString("HH-mm-ss fff")}");
            mAdornerLayer.Update();
        }
# 切换到拖动模式下,阻止隧道模式向内传递事件
        private void Exelist_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            if (tgBtn.IsChecked == true)
            {
                e.Handled = true;

                if (e.LeftButton != MouseButtonState.Pressed)
                    return;

                Point pos = e.GetPosition(exelist);
                HitTestResult result = VisualTreeHelper.HitTest(exelist, pos);
                if (result == null)
                    return;


                ListViewItem treeViewItem = VisualObjectHelper.FindVisualParent(result.VisualHit); // Find your actual visual you want to drag
                if (treeViewItem == null || treeViewItem.DataContext == null)
                    return;

                //if ((treeViewItem.DataContext as Exeter)?.ItemList.Count > 0)
                //    return;

                Exeter dataItem = treeViewItem.DataContext as Exeter;
                if (string.IsNullOrEmpty(dataItem.FileName) || !Path.HasExtension(dataItem.Path))
                    return;

                DragDropAdorner adorner = new DragDropAdorner(treeViewItem);
                mAdornerLayer = AdornerLayer.GetAdornerLayer(exelist);
                mAdornerLayer.Add(adorner);

                DataObject dataObject = new DataObject(dataItem);
                //DoDragDrop 会处理 Exelist_DragLeave 和 Exelist_DragEnter
                DragDrop.DoDragDrop(exelist, dataObject, DragDropEffects.Copy);

                mAdornerLayer?.Remove(adorner);
                mAdornerLayer = null;
            }
        }
WPF