以前、WPF でコントロールのドラッグコードを書いたのですが、業務的に少し書き直してみます。WPFでコントロールをドラッグ(1) では、マウスの down/up/move のイベントを直接つけていますが、コントロールが増えたときには面倒ですね…というか、動的にイベントを追加すればよいのですが。ふと、[WPF]枠なしでリサイズ&ドラッグ移動可能なウィンドウを作る に行き当たると、WindowChrome クラス を使うと枠なしのウィンドウが作れて、MouseLeftButtonDown イベント内に DragMove イベントを呼び出せばよいようです。この方式だと簡単ですね。
というわけで、マウスダウンのイベントだけあらかじめ付けておいて、マウスの移動とアップイベントは動的に追加します。また、クラスの継承ではなくて拡張を使って実装します。
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 | public static class ControlDragExtenstions { /// <summary> /// コントロールのドラッグを有効にする /// 親コントロールが Canvas であること /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public static void DragMove( this Control t, object sender, MouseButtonEventArgs e) { var el = sender as Control; var canvas = el.Parent as Canvas; var dragOffset = e.GetPosition(el); el.CaptureMouse(); MouseEventHandler mouseMove = null ; MouseButtonEventHandler mouseUp = null ; mouseMove = new MouseEventHandler((_, __) => { Point pt = Mouse.GetPosition(canvas); Canvas.SetLeft(el, pt.X - dragOffset.X); Canvas.SetTop(el, pt.Y - dragOffset.Y); }); mouseUp = new MouseButtonEventHandler((_, __) => { el.ReleaseMouseCapture(); el.MouseMove -= mouseMove; el.MouseUp -= mouseUp; }); el.MouseMove += mouseMove; el.MouseLeftButtonUp += mouseUp; } } |
利用するときは、次のように sender と MouseButtonEventArgs 引数をそのまま渡します。MouseButtonEventArgs のほうは、マウスの相対位置を調べるのに使います。
1 2 3 4 5 | // マウスダウンのイベント処理 card.MouseLeftButtonDown += (sender, e) => { this .DragMove(sender, e); }; |
これを動かすと、こんな感じにドラッグができるようになります。