Shoeisha Technology Media

CodeZine(コードジン)

特集ページ一覧

ドラッグ&ドロップで操作できるシフト表作成WPFアプリケーションを作る

ComponentOne Studioを活用したWindowsフォームアプリケーションの作成

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加
2013/12/25 14:00
目次

ドラッグ処理の作成

 実際にテキストブロックをドラッグできるようにする処理は、ビハインドコードで作成します。

テキストブロックのドラッグ処理

 テキストブロックのドラッグ処理は、C1DragDropManagerクラスのRegisterDropTargetメソッドを呼び出して、グリッドがドロップ先になるように指定します。

 次に、RegisterDragSourceメソッドを使用してドラッグ元にテキストブロックを指定します。

 そして、マウス座標をグリッドの座標に変換するイベントハンドラを作成し、DragDropイベントに連結します。

 これで、テキストブロックをドラッグすると、グリッドの新しい位置に移動できるようになります。

 ① 最初に、C1DragDropManagerクラスのインスタンスを作成します。

 そして、RegisterDropTargetメソッドの引数にGrid要素を指定し、グリッドをドロップ先になるように指定します。

 RegisterDropTargetメソッドは2つの引数を持ち、一つはドロップ先として機能するUIElementオブジェクト、もう一つは要素を登録する場合はtrue、登録解除する場合はfalseの論理値を指定します。

Visual Basic
Imports C1.WPF
Class MainWindow
    Public Sub New()

        ' この呼び出しはデザイナーで必要です。
        InitializeComponent()

        ' InitializeComponent() 呼び出しの後で初期化を追加します。

        'ドラッグドロップ マネージャの作成
        Dim ddmgr As New C1DragDropManager()
        ddmgr.RegisterDropTarget(Grid1, True)
C#
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」を指定します。

DragDropEffect列挙体のメンバ
メンバ名 説明
None アクションなし
Move ドラッグ元要素をドラッグ先要素に移動します
Copy ドラッグ元要素をドラッグ先要素にコピーします
Visual Basic
For Each e As UIElement In Grid1.Children
    ddmgr.RegisterDragSource(e, DragDropEffect.Move, ModifierKeys.None)
Next
C#
foreach (UIElement e in Grid1.Children)
{
    ddmng.RegisterDragSource(e, DragDropEffect.Move, ModifierKeys.None);
}

 ③ そして、C1DragDropManagerクラスのDragDropイベントに、マウス座標をグリッドの座標に変換するイベントハンドラ「Do_DragDrop」を連結します。

Visual Basic
    AddHandler ddmgr.DragDrop, AddressOf Do_DragDrop
End Sub
C#
    ddmng.DragDrop += Do_DragDrop;
}

座標変換用イベントハンドラ「Do_DragDrop」の作成

 C1DragDropManagerコンポーネントの設定が終わったら、マウス座標をグリッドの座標に変換するイベントハンドラ「Do_DragDrop」を作成します。

 DragDropイベントは、ドラッグ&ドロップ処理の最後に、ユーザーが登録されたドロップ先上でマウスボタンを放したときに発生します。

 そこで、グリッドのどの位置にドロップされたのかをマウスの位置で判断し、そこにテキストブロックを移動させます。

 ① まずマウスボタンがクリックされた位置を取得します。そして、その値からグリッドの行列番号を導き出します。

 これは、グリッドの行列の高さと幅を計算して割り出します。

Visual Basic
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
C#
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要素の子要素として依存関係にあるので、グリッドの行列番号を指定することでその位置のグリッドにテキストブロックが移動するようになります。

Visual Basic
' 要素を新しい位置に移動
e.DragSource.SetValue(Grid.RowProperty, row)
e.DragSource.SetValue(Grid.ColumnProperty, col)
C#
// 要素を新しい位置に移動
e.DragSource.SetValue(Grid.RowProperty, row);
e.DragSource.SetValue(Grid.ColumnProperty, col);

 以上で出来上がりです。

まとめ

 ドラッグ&ドロップ機能は、使い方によってはユーザーの操作性を高めてくれる便利な機能です。特にWPFアプリケーションでは、タブレット端末も視野に入れてアプリケーションを開発することもあります。アプリケーションの機能の中にドラッグ&ドロップを組み込むのであれば、C1DragDropManagerコンポーネントはきっと役に立つでしょう。



  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • 瀬戸 遥(セト ハルカ)

    8ビットコンピュータの時代からBASICを使い、C言語を独習で学びWindows 3.1のフリーソフトを作成、NiftyServeのフォーラムなどで配布。Excel VBAとVisual Basic関連の解説書を中心に現在まで40冊以上の書籍を出版。近著に、「ExcelユーザーのためのAccess再...

バックナンバー

連載:ComponentZine(ComponentOne Studio)

もっと読む

All contents copyright © 2005-2019 Shoeisha Co., Ltd. All rights reserved. ver.1.5