キャンバス内の要素を複数選択する方法を紹介します。ついでにThumbの移動方法も解説しています。
前回のWPF Canvasにマウスで図形を描画する方法で解説した内容は省略します。
概要とソースコード
ソースコード
xamlとコードはGithubの方で公開しています。
https://github.com/kame-chan/WPF/tree/master/MultiSelector
概要
マウスの左クリックを押している間にマウスの位置に対応した図形を描画し、範囲内の要素を選択します(複数可)
このプログラムから学べること
- マウスと図形の位置取得
- 動的な描画
- 既存の描画コントロールの削除
- Thumbコントロールの移動方法
- 複数コントロールの移動方法
コード解説
// パスを描画する
private void DrawRectangle(Point p)
{
...
Rect r = new Rect(init, p); //範囲確認用
RectangleGeometry rg = new RectangleGeometry(r);
frame.Data = rg;
}
マウスで描いたパスの中に要素があるかを確認する方法ですが、
Rect.IntersectsWith(Rect)でRectの重なりを確認するメソッドを利用します。
そのためにパスのRectもマウス移動イベントで記録しておきます。
// thumb選択の処理、複数選択
private void SelectThumb()
{
if (frame.Data == null) return;
Rect sr = frame.Data.Bounds; //枠のRect
Rect tr;
foreach (Thumb t in thumbList)
{
tr = new Rect(GetLocate(t), t.RenderSize); //ThumbのRect
//ThumbのRectが枠のRectと重なっているか判定
if (tr.IntersectsWith(sr))
{
t.BorderThickness = new Thickness(1);
t.Background = new SolidColorBrush(Colors.Aqua);
selectStock.Add(t);
multi = true; //boolは使わずにselectStockの数を数えて判定する方法でも良い
}
}
}
選択範囲内に要素があるかを確認するために、あらかじめ全ての要素をリストへ格納しておきます。thumbListがその格納済みリストです。
重なっているものを視覚的に分かりやすいように装飾しています。selectStockへ要素を追加することで選択要素をあとで再利用できるようにしています。
// Thumbのドラッグ移動中
private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
{
var thumb = sender as Thumb;
var canvas = thumb.Parent as Canvas;
if (multi) //複数選択している場合はthumbの移動関数を変更
{
var x = e.HorizontalChange; //マウスの移動量X
var y = e.VerticalChange; //マウスの移動量Y
foreach (Thumb t in selectStock)
{
//選択リスト内にある要素とマウスの移動量を渡す
SetLocate_Multi(t, new Point(x, y));
}
}
else
{
var x = Canvas.GetLeft(thumb) + e.HorizontalChange;
var y = Canvas.GetTop(thumb) + e.VerticalChange;
//キャンバスの領域外に出ないように数値上限を設定、複数移動の場合はもうひと工夫必要
x = Math.Max(x, 0);
y = Math.Max(y, 0);
x = Math.Min(x, canvas.ActualWidth - thumb.ActualWidth);
y = Math.Min(y, canvas.ActualHeight - thumb.ActualHeight);
SetLocate(thumb, new Point(x, y));
}
}
DragDeltaEventArgs eからはマウスの移動量が取得できるので、それと各要素の現在地を合わせて再配置しています。移動用のコントロールはThumbが良いです。
移動するコントロールが複数になると移動範囲の制御が面倒になります。上限を設けないと表示領域外まで移動する可能性があるので実装するときには気をつけましょう。