おいて、ドラッグアンドドロップ(以下、D&D)でアイテムを並べ替える方法を説明する。ドラッグ中はマウスカーソル変更だけでなく、半透明のドラッグオブジェクト(以下、ゴースト)を表示する。アイテムを並び替えるギミックだ。ひとたびゴーストを表示しようと思うと一筋縄ではいかない。中のアイテムをゴーストつきで並べ替えるコードを紹介する。そもそもこの半透明のゴースト(本当の呼び名は知らない)の情報が極端に少ない。唯一参考になったのが、下記のオノッチさんのサイトだ。全て是れ、意の如しこのページでも基本的にこのオノッチさんのコードをベースとしている(というより、ほとんどそのまま)。描画すべきであることがわかった。実装の前に、いくつかクラスを追加しておく必要がある。長くなるので、ページの最後に示す。基本的な考え方としては、アイテムでマウス左ボタンが押されたときにそのアイテムと座標を記憶アイテムで左ボタンが押されたまま、ある程度マウスが動かされればドラッグ処理を開始ドラッグ中はゴーストの座標をマウスポインタの位置に追従させるリストボックスでドロップされたときに座標を調べてアイテムを入れ替えという流れだ。面倒なので、先にイベントハンドラをすべて定義しておく。番号ごとのイベントを下記に示す。下記のように定義してやればよい。▼アイテムでマウス左ボタンが押されたときの処理(ListBoxItem.PreviewMouseLeftButtonDown)ここでは、マウスが押されたときの座標とアイテムを記憶しておく。アイテムを記憶しておくのは後からマウスが動いたときにマウスが押されたアイテムと同じかどうかを調べるためである。クラス変数として、このあとのイベントハンドラ内で共通して使う変数を定義しておく。▼マウスが動いたときの処理(ListBoxItem.PreviewMouseMove)実際にドラッグを行う部分がこのイベントハンドラである。マウス移動量がシステム設定値以上になったら、ドラッグのフェーズに入る。10行目:リストボックスへのドロップを許可する。メソッド(スタティック)でリストボックスの装飾レイヤーを得る。13行目:オーナー、装飾オブジェクト、透明度、ドラッグ開始位置を渡して、ゴーストを初期化する。)20行目:リストボックスへのドロップを禁止する。▼ドラッグ中の処理(ListBoxItem.QueryContinueDrag)ドラッグ中は常にこのイベントが発生するので、ゴーストの位置をマウスに追従させればよい。すべてウィンドウ上の位置を返した。そのため、ウィンドウ上でのリストボックスの左上の座標を求め、その分を減算して設定している。▼ドロップされたあとの処理(ListBox.Drop)ここは基本的にリストボックスのアイテムを入れ替える処理だ。インデックス入れ替え先(挿入先)のインデックスが必要である。元のコレクションの操作で行っている。取得しているが、バインドしていない場合は必要ない。3行目:ドロップされた位置を取得しておく。バインド要素が得られるので、これの元の位置を取得しておく。7行目:最初の要素からループを回し、ドロップ座標から、アイテムの新しい位置(インデックス)を割り出す。見つかればその時点で要素を入れ替えて抜ける。見つからなければ、一番最後に要素をもってきて終わり。上での座標を割り出している。いうと、ここをアイテムの前に挿入するのか、後ろに挿入するのかの判断ポイントにしているからである。上半分でドロップされた場合はそのアイテムの前に、下半分の場合はそのアイテムの後ろに追加するようにする。メソッドが用意されていたので、入れ替えはこれを利用した。三項演算子による分岐は要素が下方向に移動されたか上方向に移動されたによるものである。クラスこれはドラッグ中に装飾レイヤーに表示するゴーストのクラスである。クラスから継承される。オノッチさんのものでも十分だったが、コンストラクタの引数にアイテムのドラッグ開始位置(dragPos)を追加し、マウスが押された位置でオブジェクトをつかんでいるように見せるようにした。値をドラッグ位置に書き換えているだけである。クラスこれはオノッチさんのものと同じ。メソッドが用意されている。イベントハンドラ中でマウスカーソルの位置を取得するためである。マウスポインタ位置を返すメソッドはない。メソッドでも取得できそうだが、これはうまくいかない。利用しておくほかないようだ。確実に取得することはできません。呼び出しによって大部分の動作が制御されるためです。代わりに、次の方法を試してください。メソッドを呼び出します。Yamada(山田研二)。