- PR -

リストボックス内の項目をドラッグ&ドロップで移動させたい

1
投稿者投稿内容
さぶ〜
会議室デビュー日: 2006/05/25
投稿数: 4
投稿日時: 2006-05-25 19:01
リストボックス内の項目をドラッグ&ドロップで移動させたいのですが、うまく行きません。

1.リストボックス内の項目(複数)を選択する(Ctrl+マウス左クリック)
2.同じリストボックス内にドラッグ&ドロップする
3.ドロップした箇所に、選択した項目が移動する


リストボックスに、以下のように実装しています。
listBox.MultiColumn = false;
listBox.SelectionMode = SelectionMode.MultiExtended;
listBox.MouseDown += new MouseEventHandler(listBox_MouseDown);
listBox.DragEnter += new DragEventHandler(listBox_DragEnter);
listBox.DragDrop += new DragEventHandler(listBox_DragDrop);

そして、文末のようにイベント処理を実装しています。

ドラッグ&ドロップすると、
・あらぬところに移動する
・移動しない
という現象になります。

★印のあたりが怪しいと思っています。
Webサイトを検索しながら、ここまで見様見真似で書いてきました。
デバッグして下さる方がいれば、是非お願いします。
参考になるサイトのご教示でも結構です。宜しくお願いします。




private void listBox_MouseDown(object sender, MouseEventArgs e) {
//マウスの左ボタンだけが押されている時のみドラッグできるようにする
if(e.Button == MouseButtons.Left) {
//ドラッグの準備
ListBox lbx = (ListBox)sender;
//ドラッグするアイテムのインデックスを取得する
int itemIndex = lbx.IndexFromPoint(e.X, e.Y);
if(itemIndex < 0) return;
//ドラッグするアイテムの内容を取得する
string itemText = (string)lbx.Items[itemIndex];

//ドラッグ&ドロップ処理を開始する
DragDropEffects dde =
lbx.DoDragDrop(itemText, DragDropEffects.All);

//ドロップ効果がMoveの時はもとのアイテムを削除する
if(dde == DragDropEffects.Move)
lbx.Items.RemoveAt(itemIndex);
}
}


private void listBox_DragEnter(object sender, System.Windows.Forms.DragEventArgs e) {
if(e.Data.GetDataPresent(DataFormats.FileDrop)) {
e.Effect = DragDropEffects.All;
} else if(e.Data.GetDataPresent(typeof(string))) {
e.Effect = DragDropEffects.Move; //★ リストボックス内の移動だと、stringが入ってくる
} else {
e.Effect = DragDropEffects.None;
}
}


private void listBox_DragDrop(object sender, System.Windows.Forms.DragEventArgs e) {
if(e.Data.GetDataPresent(typeof(string))) {
ListBox lbx = (ListBox)sender;
int itemIndex = lbx.IndexFromPoint(e.X, e.Y); //★ ここの戻り値が、-1だったり想定より大きい値だったりする
string itemText = (string)e.Data.GetData(typeof(string));
this.listBox.Items.Insert(itemIndex, itemText);
} else {
string[] s = (string[])e.Data.GetData(DataFormats.FileDrop, false);
for(int i = 0; i < s.Length; i++) {
this.listBox.Items.Add(s[i]);
}
}
}
べる
ぬし
会議室デビュー日: 2003/09/20
投稿数: 1093
投稿日時: 2006-05-25 19:33
DragEventArgsのYとかXで取得できるのは画面座標みたいですよ。

DragEventArgs メンバ
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2006-05-25 20:00
宇宙仮面さんとか、どぼんさんのところに、そのものがありますよ。
さぶ〜
会議室デビュー日: 2006/05/25
投稿数: 4
投稿日時: 2006-05-25 20:03
引用:

べるさんの書き込み (2006-05-25 19:33) より:
DragEventArgsのYとかXで取得できるのは画面座標みたいですよ。

DragEventArgs メンバ



早速の返信、ありがとうございます。
DragEventArgs
は、私が記述したソースの「listBox_MouseDown」メソッドの中でも使っています。
このメソッドはドラッグ元の項目を処理しているのですが、
たとえばテキストエディタの上にドロップすると、テキストエディタには、
選択した項目がコピーされます。
ということは、DragEventArgsを使って座標軸から選択項目を判定させるのは、
うまくいっているような気がします。。。

気がするだけですが。

もしかすると、ドラッグ「先」のListBoxコントロールがうまく指定できていないのかなー

べる
ぬし
会議室デビュー日: 2003/09/20
投稿数: 1093
投稿日時: 2006-05-25 20:28
引用:
DragEventArgs
は、私が記述したソースの「listBox_MouseDown」メソッドの中でも使っています。

いや、使っていないでしょう。↓
>private void listBox_MouseDown(object sender, MouseEventArgs e) {

MouseEventArgsの場合は画面座標ではないようです。確かに画面座標とは書いてないですね。
MouseEventArgs メンバ

引用:
もしかすると、ドラッグ「先」のListBoxコントロールがうまく指定できていないのかなー

コントロールがうまく、、というか
IndexFromPointはリストボックス内の座標を指定するもので、
DragEventArgsのYとかXは、リストボックス内の座標を返すものではない、ということです。

引用:
宇宙仮面さんとか、どぼんさんのところに、そのものがありますよ。

コメント部分見る限り、どぼんさんあたりから取ってきたのでしょうね。
さぶ〜
会議室デビュー日: 2006/05/25
投稿数: 4
投稿日時: 2006-05-25 20:35
引用:

Jittaさんの書き込み (2006-05-25 20:00) より:
宇宙仮面さんとか、どぼんさんのところに、そのものがありますよ。



まさに、どぼんさんのところのソースを参考に作ったんです!
が、どぼんさんのソースは、ドロップ先リストボックスの「最後尾に」
項目を追加する例のため、今回の問題が解決できていません。
デバッガで確認したのですが、ドロップ先の位置を取得する

int itemIndex = listBox.IndexFromPoint(e.X, e.Y);

の戻り値がおかしいのが、今回の不具合のすべてです。
どうやったら、ドロップ「先」の位置(ListBox[x] だとすると、 xの値)を
取得できるのでしょうか。
さぶ〜
会議室デビュー日: 2006/05/25
投稿数: 4
投稿日時: 2006-05-25 21:34
[quote]
べるさんの書き込み (2006-05-25 20:28) より:
引用:
DragEventArgs
は、私が記述したソースの「listBox_MouseDown」メソッドの中でも使っています。

いや、使っていないでしょう。↓
>private void listBox_MouseDown(object sender, MouseEventArgs e) {

MouseEventArgsの場合は画面座標ではないようです。確かに画面座標とは書いてないですね。
MouseEventArgs メンバ

鋭いご指摘、ありがとうございました!
仰る通り、
DragEventArgsで取得できる座標:画面左上からのマウス位置
MouseEventArgsで取得できる座標:コントロール左上からのマウス位置
なので、以下のように、コントロール左上からの位置を計算してあげたらうまくいきました!

private void listBox_DragDrop(object sender, System.Windows.Forms.DragEventArgs e) {
if(e.Data.GetDataPresent(typeof(string))) {
string itemText = (string)e.Data.GetData(typeof(string));
int toX = e.X - listBox.Location.X - panelConf.Location.X - this.Left;
int toY = e.Y - listBox.Location.Y - panelConf.Location.Y - this.Top;
1

スキルアップ/キャリアアップ(JOB@IT)