zoukankan      html  css  js  c++  java
  • ListView 多行拖拽排序

    核心代码:修改ListView的属性,及绑定事件

    // 初始化listView1.  
    private void InitializeListView()
    {
        listView1.AllowDrop = true;
        listView1.ListViewItemSorter = new ListViewIndexComparer();
        //初始化插入标记  
        listView1.InsertionMark.Color = Color.Red;
        //  
        listView1.ItemDrag += listView1_ItemDrag;
        listView1.DragEnter += listView1_DragEnter;
        listView1.DragOver += listView1_DragOver;
        listView1.DragLeave += listView1_DragLeave;
        listView1.DragDrop += listView1_DragDrop;
    }
    
    // 当一个项目拖拽是启动拖拽操作  
    void listView1_ItemDrag(object sender, ItemDragEventArgs e)
    {
        Dictionary<ListViewItem, int> itemsCopy = new Dictionary<ListViewItem, int>();
        foreach (ListViewItem item in listView1.SelectedItems)
            itemsCopy.Add(item, item.Index);
        listView1.DoDragDrop(itemsCopy, DragDropEffects.Move);
    }
    
    void listView1_DragEnter(object sender, DragEventArgs e)
    {
        e.Effect = e.AllowedEffect;
    }
    
    //像拖拽项目一样移动插入标记  
    void listView1_DragOver(object sender, DragEventArgs e)
    {
        // 获得鼠标坐标  
        Point point = listView1.PointToClient(new Point(e.X, e.Y));
        // 返回离鼠标最近的项目的索引  
        int index = listView1.InsertionMark.NearestIndex(point);
        // 确定光标不在拖拽项目上  
        if (index > -1)
        {
            Rectangle itemBounds = listView1.GetItemRect(index);
            if (point.X > itemBounds.Left + (itemBounds.Width / 2))
            {
                listView1.InsertionMark.AppearsAfterItem = true;
            }
            else
            {
                listView1.InsertionMark.AppearsAfterItem = false;
            }
        }
        listView1.InsertionMark.Index = index;
    }
    
    // 当鼠标离开控件时移除插入标记  
    void listView1_DragLeave(object sender, EventArgs e)
    {
        listView1.InsertionMark.Index = -1;
    }
    
    // 将项目移到插入标记所在的位置  
    void listView1_DragDrop(object sender, DragEventArgs e)
    {
        // 返回插入标记的索引值  
        int index = listView1.InsertionMark.Index;
        // 如果插入标记不可见,则退出.  
        if (index == -1)
        {
            return;
        }
        // 如果插入标记在项目的右面,使目标索引值加一  
        if (listView1.InsertionMark.AppearsAfterItem)
        {
            index++;
        }
    
        // 返回拖拽项  
        Dictionary<ListViewItem, int> items = (Dictionary<ListViewItem, int>)e.Data.GetData(typeof(Dictionary<ListViewItem, int>));
        foreach (var item in items)
        {
            //在目标索引位置插入一个拖拽项目的副本   
            listView1.Items.Insert(index, (ListViewItem)item.Key.Clone());
            // 移除拖拽项目的原文件  
            listView1.Items.Remove(item.Key);
            if (item.Value >= index) index++;
        }
    }
    
    // 对ListView里的各项根据索引进行排序  
    class ListViewIndexComparer : System.Collections.IComparer
    {
        public int Compare(object x, object y)
        {
            return ((ListViewItem)x).Index - ((ListViewItem)y).Index;
        }
    }

    处理技巧:上述的代码大部分是直接从网上下载的,根据个人的需要做了微调。下载的代码实现单行的拖拽,修改的重点是多行的拖拽。实现这个有两个关键的地方:

    listView1_ItemDrag的DoDragDrop里面的传参和listView1_DragDrop事件里面对传递过来的数据的解析。

    解决的过程分几步:

    1. 传递当前选中的所有行。这里可以通过listView1.SelectedItems获取得到。

    2. 传递的所有行执行插入和删除。由于引用的问题,没有直接对listView1.SelectedItems进行foreach操作(Remove对这个对象同样有效。会产生变foreach边修改的情况)。复制到新的集合。

    3. 插入的顺序问题。譬如,如果是2、3、6、7插入到4后面,根据顺序执行后,会产生2376的后果,这是因为6在4之后,插入了6后,6以前的长度会增加1。解决方法,碰到6>4的情况,6插入完成之后,4++。

  • 相关阅读:
    flex 鼠标事件和效果
    查看和修改Oracle服务器端的字符集
    Oracle随机抽取数据sql
    hibernate.properties
    Oracle11g物理文件冷备份(转)
    支付宝接口使用文档说明 支付宝异步通知(notify_url)与return_url
    关于Oracle的行转列
    Intellij idea 12 tomcat日志窗口不显示问题
    在Servlet中获取来源URL
    uniapp 实现小程序列表项左滑菜单
  • 原文地址:https://www.cnblogs.com/icyJ/p/ListView_Drop.html
Copyright © 2011-2022 走看看