ドラッグ処理の作成
実際にテキストブロックをドラッグできるようにする処理は、ビハインドコードで作成します。
テキストブロックのドラッグ処理
テキストブロックのドラッグ処理は、C1DragDropManagerクラスのRegisterDropTargetメソッドを呼び出して、グリッドがドロップ先になるように指定します。
次に、RegisterDragSourceメソッドを使用してドラッグ元にテキストブロックを指定します。
そして、マウス座標をグリッドの座標に変換するイベントハンドラを作成し、DragDropイベントに連結します。
これで、テキストブロックをドラッグすると、グリッドの新しい位置に移動できるようになります。
① 最初に、C1DragDropManagerクラスのインスタンスを作成します。
そして、RegisterDropTargetメソッドの引数にGrid要素を指定し、グリッドをドロップ先になるように指定します。
RegisterDropTargetメソッドは2つの引数を持ち、一つはドロップ先として機能するUIElementオブジェクト、もう一つは要素を登録する場合はtrue、登録解除する場合はfalseの論理値を指定します。
Imports C1.WPF
Class MainWindow
Public Sub New()
' この呼び出しはデザイナーで必要です。
InitializeComponent()
' InitializeComponent() 呼び出しの後で初期化を追加します。
'ドラッグドロップ マネージャの作成
Dim ddmgr As New C1DragDropManager()
ddmgr.RegisterDropTarget(Grid1, True)
using C1.WPF;
namespace DragDropMNG_WPF_cs
{
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
C1DragDropManager ddmng = new C1DragDropManager();
ddmng.RegisterDropTarget(Grid1, true);
② 続いて、RegisterDragSourceメソッドを使用してテキストブロックをドラッグ対象のオブジェクトとして指定します。グリッド上にいくつテキストブロックがあってもドラッグ対象に設定できるように、グリッド内のオブジェクトを一つ一つサーチしドラッグ対象として設定していきます。
RegisterDragSourceメソッドは3つの引数を持ち、1つはドラッグ対象のUIElementオブジェクト、もう一つはドラッグ元をドロップ先要素にドロップしたときに実行されるアクションが、移動なのかコピーなのかを表すをDragDropEffect列挙体のメンバで指定します。
3つ目の引数は、どの修飾子キー(Shiftキー、CtrlキーおよびAltキー)が押された状態であるかを示す値を格納しているModifierKeysプロパティ(Controlクラスのメンバ値はKeys列挙体メンバ)を指定しますが、このメソッドではデフォルトの「None」を指定します。
| メンバ名 | 説明 |
|---|---|
| None | アクションなし |
| Move | ドラッグ元要素をドラッグ先要素に移動します |
| Copy | ドラッグ元要素をドラッグ先要素にコピーします |
For Each e As UIElement In Grid1.Children
ddmgr.RegisterDragSource(e, DragDropEffect.Move, ModifierKeys.None)
Next
foreach (UIElement e in Grid1.Children)
{
ddmng.RegisterDragSource(e, DragDropEffect.Move, ModifierKeys.None);
}
③ そして、C1DragDropManagerクラスのDragDropイベントに、マウス座標をグリッドの座標に変換するイベントハンドラ「Do_DragDrop」を連結します。
AddHandler ddmgr.DragDrop, AddressOf Do_DragDrop
End Sub
ddmng.DragDrop += Do_DragDrop;
}
座標変換用イベントハンドラ「Do_DragDrop」の作成
C1DragDropManagerコンポーネントの設定が終わったら、マウス座標をグリッドの座標に変換するイベントハンドラ「Do_DragDrop」を作成します。
DragDropイベントは、ドラッグ&ドロップ処理の最後に、ユーザーが登録されたドロップ先上でマウスボタンを放したときに発生します。
そこで、グリッドのどの位置にドロップされたのかをマウスの位置で判断し、そこにテキストブロックを移動させます。
① まずマウスボタンがクリックされた位置を取得します。そして、その値からグリッドの行列番号を導き出します。
これは、グリッドの行列の高さと幅を計算して割り出します。
Private Sub Do_DragDrop(source As Object, e As DragDropEventArgs)
' マウスの位置を取得
Dim MousePt As Point = e.GetPosition(Grid1)
' グリッド行/列座標に変換
Dim row As Integer, col As Integer
Dim GridPt As New Point(0, 0)
For row = 0 To Grid1.RowDefinitions.Count - 1
GridPt.Y += Grid1.RowDefinitions(row).ActualHeight
If GridPt.Y > MousePt.Y Then
Exit For
End If
Next
For col = 0 To Grid1.ColumnDefinitions.Count - 1
GridPt.X += Grid1.ColumnDefinitions(col).ActualWidth
If GridPt.X > MousePt.X Then
Exit For
End If
Next
private void Do_DragDrop(object source, DragDropEventArgs e)
{
// マウスの位置を取得
Point MousePt = e.GetPosition(Grid1);
// グリッド行/列座標に変換
int row, col;
Point GridPt = new Point(0, 0);
for (row = 0; row < Grid1.RowDefinitions.Count; row++)
{
GridPt.Y += Grid1.RowDefinitions[row].ActualHeight;
if (GridPt.Y > MousePt.Y)
break;
}
for (col = 0; col < Grid1.ColumnDefinitions.Count; col++)
{
GridPt.X += Grid1.ColumnDefinitions[col].ActualWidth;
if (GridPt.X > MousePt.X)
break;
}
② ドロップ先のグリッドの位置が決まったら、テキストブロックを移動させます。
まず、イベントハンドラの引数「DragDropEventArgs」クラスのDragSourceプロパティでドラッグ元のUIElementオブジェクトを取得します。この場合はテキストブロックなので、TextBlockクラスのSetValueメソッドを使用して移動させます。
SetValueメソッドは依存関係プロパティ識別子を指定して、依存関係プロパティのローカル値を設定するメソッドです。この場合、TextBlock要素はGrid要素の子要素として依存関係にあるので、グリッドの行列番号を指定することでその位置のグリッドにテキストブロックが移動するようになります。
' 要素を新しい位置に移動 e.DragSource.SetValue(Grid.RowProperty, row) e.DragSource.SetValue(Grid.ColumnProperty, col)
// 要素を新しい位置に移動 e.DragSource.SetValue(Grid.RowProperty, row); e.DragSource.SetValue(Grid.ColumnProperty, col);
以上で出来上がりです。
まとめ
ドラッグ&ドロップ機能は、使い方によってはユーザーの操作性を高めてくれる便利な機能です。特にWPFアプリケーションでは、タブレット端末も視野に入れてアプリケーションを開発することもあります。アプリケーションの機能の中にドラッグ&ドロップを組み込むのであれば、C1DragDropManagerコンポーネントはきっと役に立つでしょう。
