ドラッグ&ドロップで項目の順序を変更できるリストボックスを作成します。
AllowDropOtherBoxプロパティを作成することで、リストボックスを複数作成した場合、別のリストボックスに対してもドラッグ&ドロップで項目のコピーができるかも設定できるようにします。
Contents
リストボックスでドラッグ&ドロップで項目を入れ替えるために必要なこととは?
ドラッグ&ドロップを可能にするためには、AllowDropプロパティをtrueにする必要があります。それからDragOverイベントやDragDropイベントを処理する必要があるのですが、そのままではこれらのイベントは発生しません。DoDragDropメソッドを呼ぶ必要があります。
DoDragDropメソッドはどこで呼び出すか?
ではDoDragDropメソッドはどこで呼ぶのか? 他のサイトで公開されているサンプルプログラムではマウスがクリックされたときにDoDragDropメソッドを呼び出しているものもありますが、これだとマウスクリックに伴って発生する他のイベント(SelectedIndexChangedなど)が発生しなくなる場合があります。
そのためフィールド変数 bool isMouseDownを用意し、マウスボタンがおされたらこれをtrueにして離されたらfalseにしています。そしてisMouseDown == trueのときにMouseMoveイベントが発生したらドラッグが開始されたとみなしてDoDragDropメソッドを呼び出しています。
DoDragDropメソッドの引数と自作クラス DragedItemInfo
DoDragDropメソッドに渡す第一引数ですが、これはDragOverイベントやDragDropイベント発生時に取り出すことができます。ここではDragedItemInfoクラスのインスタンスを生成して、ここにドラッグが開始されたリストボックスとアイテムのインデックスを格納します。そうすればドロップされたときに項目を入れ替えるために必要な情報を取得することができます。
実際に作成したコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
public class ListBoxEx : ListBox { public ListBoxEx() { AllowDrop = true; } bool isMouseDown = false; public bool AllowDropOtherBox { set; get; } = false; public bool IsCopy { set; get; } = false; protected override void OnMouseDown(MouseEventArgs e) { isMouseDown = true; base.OnMouseDown(e); } protected override void OnMouseUp(MouseEventArgs e) { isMouseDown = false; base.OnMouseUp(e); } protected override void OnMouseMove(MouseEventArgs e) { if(isMouseDown) { isMouseDown = false; Point point = new Point(e.X, e.Y); int index = this.IndexFromPoint(point); if(index == -1) return; DragedItemInfo info = new DragedItemInfo(this, index); DoDragDrop(info, DragDropEffects.All); } base.OnMouseMove(e); } protected override void OnDragOver(DragEventArgs e) { if(e.Data.GetDataPresent(typeof(DragedItemInfo))) { Point point = this.PointToClient(new Point(e.X, e.Y)); int index = this.IndexFromPoint(point); if(index == -1) e.Effect = DragDropEffects.None; else { DragedItemInfo info = (DragedItemInfo)e.Data.GetData(typeof(DragedItemInfo)); if(info.SourceListBox == this) { if(IsCopy) { e.Effect = DragDropEffects.Copy; } else { if(info.Index == index || info.Index + 1 == index) e.Effect = DragDropEffects.None; else e.Effect = DragDropEffects.Move; } } else { if(AllowDropOtherBox && IsCopy) e.Effect = DragDropEffects.Copy; else if(AllowDropOtherBox && !IsCopy) e.Effect = DragDropEffects.Move; else e.Effect = DragDropEffects.None; } } } else e.Effect = DragDropEffects.None; base.OnDragOver(e); } protected override void OnDragDrop(DragEventArgs e) { if(e.Data.GetDataPresent(typeof(DragedItemInfo))) { Point point = this.PointToClient(new Point(e.X, e.Y)); int index = this.IndexFromPoint(point); if(index == -1) e.Effect = DragDropEffects.None; else { DragedItemInfo info = (DragedItemInfo)e.Data.GetData(typeof(DragedItemInfo)); if(info.SourceListBox == this) { if(IsCopy) { string str = (string)this.Items[info.Index]; this.Items.Insert(index, str); } else { if(index > info.Index) { string str = (string)this.Items[info.Index]; this.Items.Insert(index, str); this.Items.RemoveAt(info.Index); } else if(index < info.Index) { string s = (string)this.Items[info.Index]; this.Items.RemoveAt(info.Index); this.Items.Insert(index, s); } } } else { if(AllowDropOtherBox && IsCopy) { string str = (string)info.SourceListBox.Items[info.Index]; this.Items.Insert(index, str); } if(AllowDropOtherBox && !IsCopy) { string str = (string)info.SourceListBox.Items[info.Index]; this.Items.Insert(index, str); info.SourceListBox.Items.RemoveAt(info.Index); } } } } base.OnDragDrop(e); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public class DragedItemInfo { public DragedItemInfo(ListBoxEx sourceListBox, int index) { SourceListBox = sourceListBox; Index = index; } public ListBoxEx SourceListBox { get; protected set; } public int Index { get; protected set; } } |
使い方の一例
チェックボックス[他のリストボックスにもドロップできるようにする][移動ではなくコピーにする]のチェックを入れたり外したりして実際に移動やコピーができるか試してみてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { listBoxEx1.Items.Add("あいうえお"); listBoxEx1.Items.Add("かきくけこ"); listBoxEx1.Items.Add("さしすせそ"); listBoxEx2.Items.Add("なにぬねの"); listBoxEx2.Items.Add("はひふへほ"); listBoxEx2.Items.Add("まみむめも"); listBoxEx1.AllowDropOtherBox = checkBoxAllowDropOtherBox.Checked; listBoxEx2.AllowDropOtherBox = checkBoxAllowDropOtherBox.Checked; listBoxEx1.IsCopy = checkBoxIsCopy.Checked; listBoxEx2.IsCopy = checkBoxIsCopy.Checked; } private void checkBoxAllowDropOtherBox_CheckedChanged(object sender, EventArgs e) { listBoxEx1.AllowDropOtherBox = checkBoxAllowDropOtherBox.Checked; listBoxEx2.AllowDropOtherBox = checkBoxAllowDropOtherBox.Checked; } private void checkBoxIsCopy_CheckedChanged(object sender, EventArgs e) { listBoxEx1.IsCopy = checkBoxIsCopy.Checked; listBoxEx2.IsCopy = checkBoxIsCopy.Checked; } } |