加载中…
个人资料
邵帅
邵帅
  • 博客等级:
  • 博客积分:0
  • 博客访问:230,903
  • 关注人气:50
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
相关博文
推荐博文
谁看过这篇博文
加载中…
正文 字体大小:

C# 两个listView内部和相互拖拽,任意位置拖拽,不重复,自动排序

(2012-08-09 17:58:14)
标签:

it

这篇文章发的仓促,所以没怎么写注释,以后再把注释加上,上篇文章和这篇文章不太一样,以这篇为主!!要明白清楚两个listView的所有事件的含义,其实根本不用写mouseMove,mouseUp事件,那样更费劲。代码里要注意index,尤为重要,它是拖拽到第几个项的索引。还要注意,listview不仅要判断自己内部的拖拽,还要判断外部的拖拽!!

如下图所示:

C# <wbr>两个listView内部和相互拖拽,任意位置拖拽,不重复,自动排序

C# <wbr>两个listView内部和相互拖拽,任意位置拖拽,不重复,自动排序

    下图的代码可以写在窗体加载事件当中,也可以写在窗体构造函数当中,随意。这里的GiveFeedback事件里面可以编写在拖动时需要的操作,这里没有贴出代码,因为这是告诉大家有这个事件,可以试着写写。这里lvUsers是普通用户,lvAdmins是系统管理员。其实主要是考虑index,摸清它的值,比如:往空的一方拖拽,涉及到index为-1的情况;单方自己拖拽的时候,在拖拽还没完成时鼠标没有移移动到目标位置,而是向空的地方挪,这时index也为-1,所以为-1的情况要处理!注意,不要忘记设置排序器!

 

    顺便说一下,如果有两个listView,你想在点击项时进行对该项的某些操作,比如更新数据库、显示它的子项的值的时候,最好用click事件,而不是indexChange事件,因为点击完了第一个listView的某项,再点击第二个listView的某项,然后再点击刚才第一个listView的那个项,这时是无法触发第一个listView的indexchange事件的,因为它的index没变。

C# <wbr>两个listView内部和相互拖拽,任意位置拖拽,不重复,自动排序

以下代码为上图代码中的各种事件的详细代码:

void lvUsers_DragLeave(object sender, EventArgs e)
        {
            lvUsers.InsertionMark.Index = -1;
        }

        void lvUsers_DragOver(object sender, DragEventArgs e)
        {
            // 获得鼠标坐标 
            Point point = lvUsers.PointToClient(new Point(e.X, e.Y));
            // 返回离鼠标最近的项目的索引 
            int index = lvUsers.InsertionMark.NearestIndex(point);
            // 确定光标不在拖拽项目上 
            if (index > -1)
            {
                Rectangle itemBounds = lvUsers.GetItemRect(index);
                if (point.X > itemBounds.Left + (itemBounds.Width / 2))
                {
                    lvUsers.InsertionMark.AppearsAfterItem = true;
                }
                else
                {
                    lvUsers.InsertionMark.AppearsAfterItem = false;
                }
            }
            lvUsers.InsertionMark.Index = index;
        }

        void lvUsers_DragDrop(object sender, DragEventArgs e)
        {
            // 返回插入标记的索引值 
            int index = lvUsers.InsertionMark.Index;//预期插入的位置索引
            // 返回拖拽项 
            ListViewItem item = (ListViewItem)e.Data.GetData(typeof(ListViewItem));

            // 如果插入标记不可见,则退出. 
            if (index == -1)
            {

                //管理员里的项拖拽到空的用户列表里,index要加1即index为0,默认拖到第一个位置,否则index为-1的话,会发生拖动异常!
                if (FilterName(lvAdmins, item.Text))
                {

                     lvAdmins.Items.Remove(item);

                     //index+1默认拖拽到第一个位置
                     lvUsers.Items.Insert(index+1, (ListViewItem)item.Clone());

                }

                else//普通用户里的项拖拽到自己里的未知位置时,不发生移动!
                {
                }
                return;
            }
            // 如果插入标记在项目的右面,使目标索引值加一 
            if (lvUsers.InsertionMark.AppearsAfterItem)
            {
                index++;
            }

            
            if (FilterName(lvAdmins, item.Text))
            {

                
                lvAdmins.Items.Remove(item);

                //在目标索引位置插入一个拖拽项目的副本 
                lvUsers.Items.Insert(index, (ListViewItem)item.Clone());
            }

            else

            {

                //在目标索引位置插入一个拖拽项目的副本
                lvUsers.Items.Insert(index, (ListViewItem)item.Clone());

                // 移除拖拽项目的原文件
                lvUsers.Items.Remove(item);

            }
        }

        void lvUsers_DragEnter(object sender, DragEventArgs e)
        {
            pictureBox1.Parent = (ListView)sender;
            //e.Effect = DragDropEffects.Move;
            //进入拖拽区间发生,判断是否可以转换成指定的格式来决定是否能够进入此区域。 
            if (e.Data.GetDataPresent(typeof(ListViewItem)))//是否是真 
            {
                e.Effect = DragDropEffects.Move;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }

        }

        //用户视图列表拖放项操作完成时发生
        void lvUsers_ItemDrag(object sender, ItemDragEventArgs e)
        {
            pictureBox1.Visible = true;
            this.DoDragDrop(e.Item, DragDropEffects.Move);
        }


        void lvAdmins_DragLeave(object sender, EventArgs e)
        {
            lvAdmins.InsertionMark.Index = -1;
        }

        void lvAdmins_DragOver(object sender, DragEventArgs e)
        {
            // 获得鼠标坐标 
            Point point = lvAdmins.PointToClient(new Point(e.X, e.Y));
            // 返回离鼠标最近的项目的索引 
            int index = lvAdmins.InsertionMark.NearestIndex(point);
            // 确定光标不在拖拽项目上 
            if (index > -1)
            {
                Rectangle itemBounds = lvAdmins.GetItemRect(index);
                if (point.X > itemBounds.Left + (itemBounds.Width / 2))
                {
                    lvAdmins.InsertionMark.AppearsAfterItem = true;
                }
                else
                {
                    lvAdmins.InsertionMark.AppearsAfterItem = false;
                }
            }
            lvAdmins.InsertionMark.Index = index;
        }

        void lvAdmins_DragDrop(object sender, DragEventArgs e)
        {
            // 返回插入标记的索引值 
            int index = lvAdmins.InsertionMark.Index;//预期插入的位置索引
            // 返回拖拽项 
            ListViewItem item = (ListViewItem)e.Data.GetData(typeof(ListViewItem));

            // 如果插入标记不可见,则退出. 
            if (index == -1)
            {

                //普通用户里的项拖拽到空的管理员列表里,index要加1即index为0,默认拖到第一个位置,否则index为-1的话,会发生拖动异常!
                if (FilterName(lvUsers, item.Text))
                {

                    lvUsers.Items.Remove(item);
                    //index+1默认拖拽到第一个位置
                    lvAdmins.Items.Insert(index+1, (ListViewItem)item.Clone());
                }
                else//管理员里的项拖拽到自己里的未知位置时,不发生移动!
                {
                }
                return;
            }
            // 如果插入标记在项目的右面,使目标索引值加一 
            if (lvAdmins.InsertionMark.AppearsAfterItem)
            {
                index++;
            }

 

            //管理员拖拽到普通用户里
            if (FilterName(lvUsers, item.Text))
            {
                lvUsers.Items.Remove(item);
                //在目标索引位置插入一个拖拽项目的副本   
                lvAdmins.Items.Insert(index, (ListViewItem)item.Clone());
            }
            else//管理员自己互相拖拽
            {
                //在目标索引位置插入一个拖拽项目的副本  
                lvAdmins.Items.Insert(index, (ListViewItem)item.Clone());
                //移除拖拽项目的原文件
                lvAdmins.Items.Remove(item);
            }
        }

        void lvAdmins_DragEnter(object sender, DragEventArgs e)
        {
            pictureBox1.Parent = (ListView)sender;
            //e.Effect = DragDropEffects.Move;
            //进入拖拽区间发生,判断是否可以转换成指定的格式来决定是否能够进入此区域。 
            if (e.Data.GetDataPresent(typeof(ListViewItem)))//是否是真 
            {
                e.Effect = DragDropEffects.Move;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }

        }

        //用户视图列表拖放项操作完成时发生
        void lvAdmins_ItemDrag(object sender, ItemDragEventArgs e)
        {
            pictureBox1.Visible = true;
            this.DoDragDrop(e.Item, DragDropEffects.Move);
        }

        //判断视图里是否存在相同项
        private bool FilterName(ListView listView, string name)
        {
            for (int i = 0; i < listView.Items.Count; i++)
            {
                if (string.Equals(listView.Items[i].Text, name))
                {
                    return true;
                }
            }
            return false;
        }

 

 

        // 对ListView里的各项根据索引进行排序 
        public class ListViewIndexComparer : System.Collections.IComparer
        {
            public int Compare(object x, object y)
            {
                return ((ListViewItem)x).Index - ((ListViewItem)y).Index;
            }
        }

 

最后再说一下,如果你想点击listView中的项,获取该项的信息或对它进行操作,一定要加上

if (this.lvAdmins.FocusedItem != null){.....}进行判断。如下代码所示:

            //获取具有焦点的控件的项,这个if是必须的,不然会得到值但会报错
            if (this.lvUsers.FocusedItem != null)
            {

                //清除列表
                lbAllFunction.Items.Clear();
                lbUserFunction.Items.Clear();
                //判断右键菜单“删除普通用户”和“删除管理员”是否启用
                DeleteUserMenuStripIsOrNo();
              
  //获得选中项的名称
                string userName = lvUsers.FocusedItem.SubItems[0].Text.Trim();

            }

    Click事件可以通过FocusedItem来获得点中的项,鼠标左键、右键点击都会触发该事件,但是在鼠标左右点击listView里面的空白处,Click事件不会被触发!!

    MouseDown事件也可以通过FocusedItem来获得点中的项,鼠标左键、右键点击也都会触发该事件,但是在鼠标左右点击listView里面的空白处时,FocusedItem的值默认为该listView中第一个项!但是MouseDown事件会被触发!

    所以如果要是对项进行操作,最好用Click事件,而非MouseDown事件。一定要考虑点击空白处的情况!!

    MouseDown事件可以用在单击空白处时的判断,如“删除用户”,点击空白处时应不可删除用户,只有在点击到某一项时才可以删除,如下图所示的右键菜单栏的“删除普通用户”就是由Click和MouseDown联合控制的:

               C# <wbr>两个listView内部和相互拖拽,任意位置拖拽,不重复,自动排序

          C# <wbr>两个listView内部和相互拖拽,任意位置拖拽,不重复,自动排序






 

 

0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4000520066 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有