ドラッグ・ドロップ
TreeView 自体はドラッグ・ドロップしないようです。
マウスイベントを使って作ることはできます。
1.要点
- TreeView の ノードは、TreeViewItem を継承する。マウスイベントはノードが処理する。
- マウスボタンを操作するとイベントは、親のノードでも発生する。
2.ドラッグ
マウス左ボタン・ダウンでドラッグが始まります。このときマウスポインタの下にあるノードが引き摺られる対象です。実際には、マウスポインタの下のノードでだけ事象が発生することでドラッグ対象が認識されます。(ただし、親ノードでもイベントが発生するのでフィルタが必要です。)
- protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
- {
- if (((Window1)App.Current.MainWindow).bLevelEditMode)
- {
- if (e.RightButton == MouseButtonState.Released)
- {
- //上位のノードでもイベント発生するようだ
- if (DragNode < 0)
- {
- DragNode = id; //ドラッグするノードを記憶
- NodeOnCursor = Cursors.Hand; //カーソル形状変更
- return;
- }
- }
- }
- base.OnMouseLeftButtonDown(e);
- }
- bLevelEditMode は、アプリケーションの都合でドラッグ・ドロップ有効無効を設定。
- DragNode は、スタティックな変数で全ノードで一義。ドラッグノードを記録する。
- 一旦、DragNode が設定されたら、以降はスキップすることで、親ノードで発生するイベントをフィルタする。
- カーソルの形状を変更。実際の変更は、OnQueryCursor()で行われる。
3.ドロップ
マウス左ボタン・アップでドロップします。このときマウスポインタの下にあるノードが移動先を示します。ドロップと同様事象が発生したノードが該当します。
- protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
- {
- if (((Window1)App.Current.MainWindow).bLevelEditMode)
- {
- if ((DragNode >= 0)&&(DragNode!=id))
- {
- if (e.RightButton == MouseButtonState.Released)
- {
- source = DragNode;
- destination = id;
- //挿入位置を指定するメニューを表示。「下の階層を作成...」は子がないとき。
- ((MenuItem)NodeMoveContextMenu.Items[3]).IsEnabled = !HasItems;
- NodeMoveContextMenu.PlacementTarget = this;
- NodeMoveContextMenu.IsOpen = true;
- ResetDrag();
- return;
- }
- }
- }
- ResetDrag();
- base.OnMouseLeftButtonUp(e);
- }
- マウス左ボタンアップ・イベントが発生したノードでは、移動先を指定するコンテキストメニューを表示する。
- コンテキストメニューが閉じるまでブロックする。
- コンテキストメニューでは、このノードの前後、あるいは子ノードなど移動先を聞く。これを選択したら、その処理で移動を行う。
4.その他の処理
マウス左ボタン・ダウンからアップまでの間に、他の操作が行われたらドラッグを中止するようにすることが必要です。
|