博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
可拖拽的ListBox
阅读量:4984 次
发布时间:2019-06-12

本文共 13368 字,大约阅读时间需要 44 分钟。

  之前在写播放器的时候,遇到了一个问题,现在播放器无论是千千,KuGoo还是比较原始的MediaPlayer,它们的播放表都是可以拖拽的,直接把文件拖到播放表实现歌曲的添加那个先暂且不说,光是播放表里面的歌曲次序也可以通过拖拽来调整。但是VS提供的ListBox没能直接通过设定某个属性实现这个拖拽排序,于是俺就开始了实现这功能的探索,无意中还找到了ListBox与ListBox之间元素的拖拽,于是一并实现了,遂述此文以记之。

  其实无论是ListBox里的拖拽排序,还是ListBox间的拖动,都是通过三个事件来实现的:DragDrop,DragOver和MouseDown,对于整个拖拽的过程来说,三个事件的触发顺序是MouseDown->DragOver->DragDrop。对于拖拽排序和控件间的拖动,代码会有所差异。下面则一分为二的说说各自的处理,由于我这里是扩展控件的,直接重写ListBox类的Onxxx方法。如果直接使用ListBox控件的话,就要在这三个事件绑定的方法里面写了。

  拖拽排序  

protected override void  OnMouseDown(MouseEventArgs e)        {            base.OnMouseDoubleClick(e);            if (this.Items.Count == 0 || e.Button != MouseButtons.Left || this.SelectedIndex == -1 || e.Clicks == 2)                return;                        int index = this.SelectedIndex;            object item = this.Items[index];            DragDropEffects dde = DoDragDrop(item,                DragDropEffects.All);        }

首先要判断一下当前的ListBox有没有元素,还有鼠标有没有点中元素。接着到拖拽的过程

protected override void OnDragOver(DragEventArgs drgevent)        {            base.OnDragOver(drgevent);            drgevent.Effect = DragDropEffects.Move;        }

最后到拖放结束,鼠标按键松开的时候触发

protected override void OnDragDrop(DragEventArgs drgevent)        {            base.OnDragDrop(drgevent);            object item = dragSource.SelectedItem;                int index = this.IndexFromPoint(this.PointToClient(new Point(drgevent.X, drgevent.Y)));                this.Items.Remove(item);                if (index < 0)                    this.Items.Add(item);                else                    this.Items.Insert(index, item);        }

主要是获取那个被选中(后来就被拖动)的那个元素,然后把它从ListBox先移除,从鼠标当前的坐标来获取到所在元素的索引值,那个位置,那个索引就是被拖拽的元素的新位置,用Insert把它插进去。

  ListBox间的拖动

 

  这个就要先知道各个方法究竟是那个控件的事件触发时调用的。其余大体上跟上面的是一致的。

  举个例子,现在有两个ListBox lst1,lst2。我把lst1的一个元素拖到lst2中去,事件触发的队列是这样的

  Lst1.MouseDown=>lst1.DragOver=>lst1.DragOver=>….lst1.DragOver=>lst2.DragOver=>lst2.DragOver=>…..=>lst2.DragOver=>lst2.DragDrop

由于整个流程涉及到两个控件,最后元素的添加与元素的删除分别是两个控件的事,于是我这里就另外声明多一个静态字段来存放那个lst1。记录来源的ListBox只能在MouseDown记录了。

public static ListBox dragSource;        protected override void  OnMouseDown(MouseEventArgs e)        {            base.OnMouseDoubleClick(e);            if (this.Items.Count == 0 || e.Button != MouseButtons.Left || this.SelectedIndex == -1 || e.Clicks == 2)                return;            dragSource = this;                        int index = this.SelectedIndex;            object item = this.Items[index];            DragDropEffects dde = DoDragDrop(item,                DragDropEffects.All);        }

除了dragSource = this;外,其余都与拖拽排序的一样。

protected override void OnDragOver(DragEventArgs drgevent)        {            base.OnDragOver(drgevent);            drgevent.Effect = DragDropEffects.Move;        }

这个可以说跟拖拽排序的一模一样了。

protected override void OnDragDrop(DragEventArgs drgevent)        {            base.OnDragDrop(drgevent);            object item = dragSource.SelectedItem;            if ( dragSource != this)            {                dragSource.Items.Remove(item);                this.Items.Add(item);            }                    }

  因为是ListBox间的拖动,所以源ListBox和目标ListBox不能一样,处理还更简单,从源ListBox把元素删掉,然后增加到当前的ListBox中来。 

  如果想要既要控件间的拖动,拖动后又要按位置插入,那就把两个处理融合一下咯,本文末尾有我拓展控件的整份源码。需要的园友可以展开来看一下。

  

  交替颜色

 

  下面还介绍我另外一个拓展,就是单双行的交替颜色。记得以前的千千的播放表是有交替颜色的,现在的不知道,太久没用了,KuGoo现在的没有了,MediaPlayer12的也没有。

  我这里是重写OnDrawItem,直接拖控件的可以用DrawItem时间,接下来就是GDI+的内容了。

protected override void OnDrawItem(DrawItemEventArgs e)        {            if (this.Items.Count < 0) return;            if (e.Index < 0) return;            bool selected = (e.State & DrawItemState.Selected) == DrawItemState.Selected;            if(selected)                e.Graphics.FillRectangle(selectRowBursh, e.Bounds);            else if (e.Index % 2 != 0)                e.Graphics.FillRectangle(OddRowBursh, e.Bounds);            else                e.Graphics.FillRectangle(EvenRowBursh, e.Bounds);            if(selected)            {                e.Graphics.DrawString(this.GetItemText(e.Index), e.Font,                            selectFontBursh, e.Bounds);                            }            else            {                e.Graphics.DrawString(this.GetItemText(e.Index), e.Font,                            normalFontBursh, e.Bounds);            }            e.DrawFocusRectangle();            base.OnDrawItem(e);        }

  值得一提的是这里判断选中的不是用e.Index==this.SelectedIndex,而是用(e.State & DrawItemState.Selected) == DrawItemState.Selected,当ListBox的选择模式用了多选而不是单选的时候,调用Select属性会报错,这个也是上面拖拽的局限性,当ListBox是多选的时候,上面的拖拽就会抛异常了,而且如果单纯用e.Index==this.SelectIndex的话,选择了一个元素,当在选择另一个元素的时候,之前选择过的元素的高亮状态不会消失,这个是什么原因我也没搞懂。如果有哪位园友知道的,麻烦指点一下。

  最后附上整个控件的源码

 

1     public class DragableListBox:ListBox  2     {  3         #region 字段  4         private bool isDraw; //是否执行绘制  5         SolidBrush evenRowBursh ;  6         SolidBrush oddRowBursh;  7         Brush normalFontBursh=SystemBrushes.ControlText;  8         Brush selectFontBursh = SystemBrushes.HighlightText;  9         Brush selectRowBursh =  SystemBrushes.Highlight; 10         private bool dragAcross; 11         private bool dragSort; 12  13         public static ListBox dragSource; 14         #endregion 15  16         public DragableListBox() 17         { 18             this.DoubleBuffered = true; 19             this.OddColor = this.BackColor; 20         } 21  22         #region 外放成员 23  24         #region 属性 25  26         [Description("跨ListBox拖放元素"), Category("行为")] 27         public bool DragAcross  28         { 29             get { return (dragAcross&&AllowDrop&&SelectionMode== System.Windows.Forms.SelectionMode.One); } 30             set  31             { 32                 dragAcross = value; 33                 if (value) this.AllowDrop = true; 34             } 35         } 36  37         [Description("元素拖动排序"),Category("行为")] 38         public bool DragSort 39         { 40             get { return dragSort && AllowDrop && SelectionMode == System.Windows.Forms.SelectionMode.One; } 41             set 42             { 43                 dragSort = value; 44                 if (value) this.AllowDrop = true; 45             } 46         } 47  48         private Color oddColor; 49         [Description("单数行的底色"), Category("外观")] 50         public Color OddColor 51         { 52             get { return oddColor; } 53             set  54             { 55                 oddColor = value; 56                 isDraw = oddColor != this.BackColor; 57                 if (isDraw) DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed; 58                 else DrawMode = System.Windows.Forms.DrawMode.Normal; 59             } 60         } 61  62         #endregion 63  64         #region 事件 65  66         [Description("跨ListBox拖拽完成后触发"),Category("行为")] 67         public event DraggdHandler DraggedAcross; 68  69         [Description("拖拽排序后触发"), Category("行为")] 70         public event DraggdHandler DraggedSort; 71  72         #endregion 73  74         #endregion 75  76         #region 重写方法 77  78         #region 拖拽 79  80         protected override void OnDragDrop(DragEventArgs drgevent) 81         { 82             base.OnDragDrop(drgevent); 83             if (!DragAcross && !DragSort) return; 84  85             object item = dragSource.SelectedItem; 86  87             if (DragAcross && !DragSort && dragSource != this) 88             { 89                 dragSource.Items.Remove(item); 90                 this.Items.Add(item); 91                 if (DraggedAcross != null) 92                     DraggedAcross(this, new DraggedEventArgs() { DragItem=item, SourceControl=dragSource }); 93             } 94             else if (DragSort &&(( dragSource == this&&! DragAcross)||DragAcross)) 95             { 96                 int index = this.IndexFromPoint(this.PointToClient(new Point(drgevent.X, drgevent.Y))); 97                 dragSource.Items.Remove(item); 98                 if (index < 0) 99                     this.Items.Add(item);100                 else101                     this.Items.Insert(index, item);102                 if (DragAcross && DraggedAcross != null)103                     DraggedAcross(this, new DraggedEventArgs() { DragItem=item,SourceControl=dragSource });104                 if (DraggedSort != null)105                     DraggedSort(this, new DraggedEventArgs() { DragItem=item,SourceControl=dragSource, DestineIndex=index });106             }107             108         }109 110         protected override void OnDragOver(DragEventArgs drgevent)111         {112             base.OnDragOver(drgevent);113             if (!DragAcross&&!DragSort) return;114 115             //dragDestince=this;116             drgevent.Effect = DragDropEffects.Move;117         }118 119         protected override void  OnMouseDown(MouseEventArgs e)120         {121             base.OnMouseDoubleClick(e);122             if (!DragAcross && !DragSort ) return;123 124             if (this.Items.Count == 0 || e.Button != MouseButtons.Left || this.SelectedIndex == -1 || e.Clicks == 2)125                 return;126             dragSource = this;127             128             int index = this.SelectedIndex;129             object item = this.Items[index];130             DragDropEffects dde = DoDragDrop(item,131                 DragDropEffects.All);132         }133 134         #endregion 135 136         #region 绘制137 138         protected override void OnDrawItem(DrawItemEventArgs e)139         {140             if (this.Items.Count < 0) return;141             if (!isDraw) return;142             if (e.Index < 0) return;143             bool selected = (e.State & DrawItemState.Selected) == DrawItemState.Selected;144             if(selected)145             //if (e.Index == this.SelectedIndex)146                 e.Graphics.FillRectangle(selectRowBursh, e.Bounds);147             else if (e.Index % 2 != 0)148                 e.Graphics.FillRectangle(OddRowBursh, e.Bounds);149             else150                 e.Graphics.FillRectangle(EvenRowBursh, e.Bounds);151 152             //if (e.Index == this.SelectedIndex )153             if(selected)154             {155                 e.Graphics.DrawString(this.GetItemText(e.Index), e.Font,156                             selectFontBursh, e.Bounds);157                 158             }159             else160             {161                 e.Graphics.DrawString(this.GetItemText(e.Index), e.Font,162                             normalFontBursh, e.Bounds);163             }164             e.DrawFocusRectangle();165             base.OnDrawItem(e);166         }167 168         protected override void Dispose(bool disposing)169         {170             base.Dispose(disposing);171             if (oddRowBursh != null) oddRowBursh.Dispose();172             if (evenRowBursh != null) evenRowBursh.Dispose();173         }174 175         #endregion176 177         #endregion178 179         #region 私有方法和属性180 181         private SolidBrush EvenRowBursh182         {183             get 184             {185                 if(evenRowBursh==null)186                 {187                     evenRowBursh = new SolidBrush(this.BackColor);188                     return evenRowBursh;189                 }190                 if ( evenRowBursh.Color == this.BackColor)return evenRowBursh;191                 evenRowBursh.Dispose();192                 evenRowBursh = new SolidBrush(this.BackColor);193                 return evenRowBursh;194             }195             set 196             {197                 if(evenRowBursh!=null) evenRowBursh.Dispose();198                 evenRowBursh = value;199             }200         }201 202         private SolidBrush OddRowBursh203         {204             get 205             {206                 if (oddRowBursh == null)207                 {208                     oddRowBursh = new SolidBrush(this.OddColor);209                     return oddRowBursh;210                 }211                 if (oddRowBursh.Color == this.OddColor) return oddRowBursh;212                 oddRowBursh.Dispose();213                 oddRowBursh = new SolidBrush(this.OddColor);214                 return oddRowBursh;215             }216             set 217             {218                 if (oddRowBursh != null) oddRowBursh.Dispose();219                 oddRowBursh = value;220             }221         }222 223         private string GetItemText(int index)224         {225             try226             {227                 object item = this.Items[index];228                 if (string.IsNullOrEmpty(this.DisplayMember) || string.IsNullOrWhiteSpace(this.DisplayMember))229                     return item.ToString();230                 PropertyInfo proInfo = item.GetType().GetProperty(this.DisplayMember);231                 return proInfo.GetValue(item, null).ToString();232             }233             catch { return this.Name; }234         }235 236         #endregion237 238         public class DraggedEventArgs:EventArgs239         {240             public ListBox SourceControl { get; set; }241 242             public object DragItem { get; set; }243 244             public int DestineIndex { get; set; }245 246             public DraggedEventArgs()247             {248                 DestineIndex = -1;249             }250         }251 252         public delegate void DraggdHandler(object sender, DraggedEventArgs e);253     }
DragableListBox

 

转载于:https://www.cnblogs.com/HopeGi/p/3300276.html

你可能感兴趣的文章
模糊查询和聚合函数
查看>>
[批处理]批量将文件名更名为其上级目录名
查看>>
如何查找ORACLE中的跟踪文件
查看>>
SQL Server将一列的多行内容拼接成一行
查看>>
Spring Controller RequestMapping
查看>>
socket
查看>>
小程序 跳转问题 (来源见注明)
查看>>
JBPM4入门——9.自动节点单线执行
查看>>
//停止关联的进程
查看>>
SQL 生成公曆和農曆對照數據,公曆查找農曆和農曆查找公曆函數
查看>>
为何场效应管要用UGD与UGS(off)来比较判断夹断情况?
查看>>
.pem证书转xml格式字符串(.net)
查看>>
js构建ui的统一异常处理方案(二)
查看>>
三线程连续打印ABC
查看>>
ECharts
查看>>
初识网络爬虫
查看>>
git push 时不用每次都输入密码的方法
查看>>
54点提高PHP编程效率 引入缓存机制提升性能
查看>>
编解码-marshalling
查看>>
CDN原理
查看>>