ドラッグ アンド ドロップ ジェスチャを認識する

.NET Multi-platform App UI (.NET MAUI) ドラッグ アンド ドロップ ジェスチャ認識エンジンを使用すると、項目とそれに関連付けられているデータ パッケージを、連続するジェスチャを使用して、画面上のある位置から別の位置にドラッグできます。 ドラッグ アンド ドロップは 1 つのアプリケーション内で行うことも、あるアプリケーションで開始して別で終了することもできます。

ドラッグ ジェスチャが開始される要素である "ドラッグ ソース" では、データ パッケージ オブジェクトを設定することにより、転送されるデータを提供できます。 ドラッグ ソースが解放されると、ドロップが発生します。 その後、ドラッグ ソースの下にある要素である "ドロップ ターゲット" により、データ パッケージが処理されます。

アプリでドラッグ アンド ドロップを有効にする手順は次のとおりです。

  1. DragGestureRecognizer オブジェクトを GestureRecognizers コレクションに追加することによって、要素のドラッグを有効にします。 詳細については、「ドラッグを有効にする」を参照してください。
  2. (省略可能) データ パッケージを構築します。 画像コントロールやテキスト コントロールの場合は、.NET MAUI によってデータ パッケージを自動的に入力しますが、他のコンテンツについては、ユーザー独自のデータ パッケージを作成する必要があります。 詳細については、「データ パッケージを作成する」を参照してください。
  3. DropGestureRecognizer オブジェクトを GestureRecognizers コレクションに追加することによって、要素のドロップを有効にします。 詳細については、「ドロップを有効にする」を参照してください。
  4. (省略可能) DropGestureRecognizer.DragOver イベントを処理することにより、ドロップ ターゲットによって許可される操作の種類を示します。 詳細については、「DragOver イベントを処理する」を参照してください。
  5. (省略可能) データ パッケージを処理し、ドロップされたコンテンツを受け取ります。 画像データとテキスト データは .NET MAUI によってデータ パッケージから自動的に取得されますが、他のコンテンツについてはユーザーがデータ パッケージを処理する必要があります。 詳細については、「データ パッケージを処理する」を参照してください。

ドラッグを有効にする

.NET MAUI では、ドラッグ ジェスチャの認識機能は DragGestureRecognizer クラスで提供されます。 このクラスでは、次のプロパティが定義されています。

これらのプロパティは、BindableProperty オブジェクトが基になっています。つまり、これらは、データ バインディングの対象にすることができ、スタイルを設定できます。

DragGestureRecognizer クラスは、CanDrag プロパティが true の場合に発生する DragStarting イベントと DropCompleted イベントも定義します。 DragGestureRecognizer オブジェクトによってドラッグ ジェスチャが検出されると、DragStartingCommand が実行されて、DragStarting イベントが呼び出されます。 その後、DragGestureRecognizer オブジェクトによってドロップ ジェスチャの完了が検出されると、DropCompletedCommand が実行されて、DropCompleted イベントが呼び出されます。

DragStarting イベントに付随する DragStartingEventArgs オブジェクトでは、次のプロパティが定義されています。

  • Cancel: bool 型、イベントを取り消す必要があるかどうかを示します。
  • Data: DataPackage 型、ドラッグ ソースに付随するデータ パッケージを示します。 これは、読み取り専用プロパティです。
  • PlatformArgs: PlatformDragStartingEventArgs? 型、イベントに関連付けられているプラットフォーム固有の引数を表します。

Android では、PlatformDragStartingEventArgs クラスは次のプロパティを定義します。

  • Sender (View 型): イベントにアタッチされたネイティブ ビューを表します。
  • MotionEvent: MotionEvent 型、ドラッグ アンド ドロップ状態の情報を含むイベントを表します。

さらに、Android では、PlatformDragStartingEventArgs クラスは次のメソッドを定義します。

  • SetDragShadowBuilder: ドラッグの開始時に使用する View.DragShadowBuilder を設定します。
  • SetClipData: ドラッグの開始時に使用する ClipData を設定します。
  • SetLocalData: ドラッグの開始時に使用するローカル データを設定します。
  • SetDragFlags: ドラッグの開始時に使用する DragFlags を設定します。

たとえば、ドラッグした項目に ClipData を関連付けるには、SetClipData メソッドを使用します。

void OnDragStarting(object sender, DragStartingEventArgs e)
{
#if ANDROID
    string content = "insert your content here";
    e.PlatformArgs.SetClipData(Android.Content.ClipData.NewPlainText("Drag data", content));
#endif
}

DropCompleted イベントに付随する DropCompletedEventArgs オブジェクトには、このイベントに関連付けられているプラットフォーム固有の引数を表す、PlatformDropCompletedEventArgs? 型の PlatformArgs プロパティを定義します。

Android では、PlatformDropCompletedEventArgs クラスは次のプロパティを定義します。

  • Sender (View 型): イベントにアタッチされたネイティブ ビューを表します。
  • DragEvent (DragEvent 型): ドラッグ アンド ドロップ操作中のさまざまな時点で送信されるイベントを表します。

次に示す XAML の例は、Image に関連付けられている DragGestureRecognizer です。

<Image Source="monkeyface.png">
    <Image.GestureRecognizers>
        <DragGestureRecognizer />
    </Image.GestureRecognizers>
</Image>

この例では、Image でドラッグ ジェスチャを開始できます。

ヒント

ドラッグ ジェスチャは、長押しした後にドラッグすると開始されます。

データ パッケージを作成する

次のコントロールの場合、ドラッグを開始すると、.NET MAUI によりデータ パッケージが自動的に作成されます。

次の表では、テキスト コントロールでドラッグが開始されたときに読み取られるプロパティと、試みられる変換を示します。

コントロール プロパティ 変換
CheckBox IsChecked boolstring に変換されます。
DatePicker Date DateTimestring に変換されます。
Editor Text
Entry Text
Label Text
RadioButton IsChecked boolstring に変換されます。
Switch IsToggled boolstring に変換されます。
TimePicker Time TimeSpanstring に変換されます。

テキストと画像以外のコンテンツの場合は、データ パッケージを自分で作成する必要があります。

データ パッケージは DataPackage クラスによって表され、次のプロパティが定義されています。

DataPackagePropertySet クラスは、Dictionary<string,object> として格納されるプロパティ バッグを表します。 DataPackageView クラスの詳細については、「データ パッケージを処理する」を参照してください。

画像データまたはテキスト データを格納する

画像データまたはテキスト データをドラッグ ソースと関連付けるには、DataPackage.Image または DataPackage.Text プロパティにデータを格納します。 DragStarting イベントのハンドラーにデータを追加できます。

次の XAML の例では、DragStarting イベントのハンドラーを登録する DragGestureRecognizer を示します。

<Path Stroke="Black"
      StrokeThickness="4">
    <Path.GestureRecognizers>
        <DragGestureRecognizer DragStarting="OnDragStarting" />
    </Path.GestureRecognizers>
    <Path.Data>
        <!-- PathGeometry goes here -->
    </Path.Data>
</Path>

この例では、DragGestureRecognizerPath オブジェクトにアタッチされます。 Path でドラッグ ジェスチャが検出されると DragStarting イベントが発生し、OnDragStarting イベント ハンドラーが実行されます。

void OnDragStarting(object sender, DragStartingEventArgs e)
{
    e.Data.Text = "My text data goes here";
}

DragStarting イベントに付随する DragStartingEventArgs オブジェクトには、DataPackage 型の Data プロパティがあります。 この例では、DataPackage オブジェクトの Text プロパティが string に設定されます。 その後、ドロップ時に DataPackage にアクセスして、string を取得できます。

プロパティ バッグにデータを格納する

画像やテキストを含むどのようなデータでも、DataPackage.Properties コレクションにデータを格納することにより、ドラッグ ソースと関連付けることができます。 DragStarting イベントのハンドラーにデータを追加できます。

次の XAML の例では、DragStarting イベントのハンドラーを登録する DragGestureRecognizer を示します。

<Rectangle Stroke="Red"
           Fill="DarkBlue"
           StrokeThickness="4"
           HeightRequest="200"
           WidthRequest="200">
    <Rectangle.GestureRecognizers>
        <DragGestureRecognizer DragStarting="OnDragStarting" />
    </Rectangle.GestureRecognizers>
</Rectangle>

この例では、DragGestureRecognizerRectangle オブジェクトにアタッチされます。 Rectangle でドラッグ ジェスチャが検出されると DragStarting イベントが発生し、OnDragStarting イベント ハンドラーが実行されます。

void OnDragStarting(object sender, DragStartingEventArgs e)
{
    Shape shape = (sender as Element).Parent as Shape;
    e.Data.Properties.Add("Square", new Square(shape.Width, shape.Height));
}

DragStarting イベントに付随する DragStartingEventArgs オブジェクトには、DataPackage 型の Data プロパティがあります。 Dictionary<string, object> コレクションである DataPackage オブジェクトの Properties コレクションを変更して、任意の必要なデータを格納することができます。 この例では、"Square" キーに対する Rectangle のサイズを表す Square オブジェクトを格納するために、Properties ディクショナリが変更されています。

ドロップを有効にする

.NET MAUI では、ドロップ ジェスチャの認識は DropGestureRecognizer クラスによって提供されます。 このクラスでは、次のプロパティが定義されています。

  • AllowDrop: bool 型、ジェスチャ認識エンジンがアタッチされている要素をドロップ ターゲットにすることができるかどうかを示します。 このプロパティの既定値は true です。
  • DragOverCommand: ICommand型、ドラッグ ソースがドロップ ターゲット上にドラッグされたときに実行されます。
  • DragOverCommandParameter: object 型、DragOverCommand に渡されるパラメーター。
  • DragLeaveCommand: ICommand 型、ドラッグ ソースがドロップ ターゲット外にドラッグされたときに実行されます。
  • DragLeaveCommandParameter: object 型、DragLeaveCommand に渡されるパラメーター。
  • DropCommand: ICommand型、ドラッグ ソースがドロップ ターゲットにドロップされたときに実行されます。
  • DropCommandParameter: object 型、DropCommand に渡されるパラメーター。

これらのプロパティは、BindableProperty オブジェクトが基になっています。つまり、これらは、データ バインディングの対象にすることができ、スタイルを設定できます。

また、DropGestureRecognizer クラスには、AllowDrop プロパティが true の場合に発生する DragOverDragLeaveDrop の各イベントも定義されます。 DropGestureRecognizer によってドロップ ターゲット上でドラッグ ソースが認識されると、DragOverCommand が実行されて、DragOver イベントが呼び出されます。 次に、ドラッグ ソースがドロップ ターゲット外にドラッグされると、DropGestureRecognizer によって DragLeaveCommand が実行され、DragLeave イベントが呼び出されます。 最後に、DropGestureRecognizer によってドロップ ターゲット上でドロップ ジェスチャが認識されると、DropCommand が実行されて、Drop イベントが呼び出されます。

DragOverDragLeave のイベントに付随する DragEventArgs クラスでは、次のプロパティが定義されています。

  • Data (DataPackage 型): ドラッグ ソースに関連付けられたデータが格納されます。 このプロパティは読み取り専用です。
  • AcceptedOperation (DataPackageOperation 型): ドロップ ターゲットによって許可されている操作を指定します。
  • PlatformArgs (PlatformDragEventArgs? 型): イベントに関連付けられているプラットフォーム固有の引数を表します。

Android では、PlatformDragEventArgs クラスは次のプロパティを定義します。

  • Sender (View 型): イベントにアタッチされたネイティブ ビューを表します。
  • DragEvent (DragEvent 型): ドラッグ アンド ドロップ操作中のさまざまな時点で送信されるイベントを表します。

DataPackageOperation 列挙型の詳細については、「DragOver イベントを処理する」を参照してください。

Drop イベントに付随する DropEventArgs クラスでは、次のプロパティが定義されています。

  • Data (DataPackageView 型): データ パッケージの読み取り専用バージョンです。
  • Handled (bool 型): イベント ハンドラーでイベントが処理されたか、または .NET MAUI で独自の処理を続行する必要があるかを示します。
  • PlatformArgs (PlatformDropEventArgs? 型): イベントに関連付けられているプラットフォーム固有の引数を表します。

Android では、PlatformDropEventArgs クラスは次のプロパティを定義します。

  • Sender (View 型): イベントにアタッチされたネイティブ ビューを表します。
  • DragEvent (DragEvent 型): ドラッグ アンド ドロップ操作中のさまざまな時点で送信されるイベントを表します。

次に示す XAML の例は、Image に関連付けられている DropGestureRecognizer です。

<Image BackgroundColor="Silver"
       HeightRequest="300"
       WidthRequest="250">
    <Image.GestureRecognizers>
        <DropGestureRecognizer />
    </Image.GestureRecognizers>
</Image>

この例では、ドラッグ ソースが Image ドロップ ターゲットにドロップされると、ドラッグ ソースが ImageSource である場合は、ドラッグ ソースがドロップ ターゲットにコピーされます。 .NET MAUI は、ドラッグされた画像とテキストを互換性のあるドロップ ターゲットに自動的にコピーします。

DragOver イベントを処理する

必要に応じて DropGestureRecognizer.DragOver イベントを処理し、ドロップ ターゲットによって許可されている操作の種類を示すことができます。 DragOver イベントに付随する DragEventArgs オブジェクトに対して DataPackageOperation 型の AcceptedOperation プロパティを設定することで、許容される操作を指定できます。

DataPackageOperation 列挙型には、次のメンバーが定義されています。

  • None は、何も実行されないことを示します。
  • Copy は、ドラッグ ソースのコンテンツがドロップ ターゲットにコピーされることを示します。

重要

DragEventArgs オブジェクトが作成されるとき、AcceptedOperation プロパティの既定値は DataPackageOperation.Copy に設定されます。

次の XAML の例では、DragOver イベントのハンドラーを登録する DropGestureRecognizer を示します。

<Image BackgroundColor="Silver"
       HeightRequest="300"
       WidthRequest="250">
    <Image.GestureRecognizers>
        <DropGestureRecognizer DragOver="OnDragOver" />
    </Image.GestureRecognizers>
</Image>

この例では、DropGestureRecognizerImage オブジェクトにアタッチされます。 DragOver イベントは、ドラッグ ソースがドロップ ターゲットの上にドラッグされ、まだドロップされていない場合に発生し、OnDragOver イベント ハンドラーが実行されます。

void OnDragOver(object sender, DragEventArgs e)
{
    e.AcceptedOperation = DataPackageOperation.None;
}

この例では、DragEventArgs オブジェクトの AcceptedOperation プロパティが DataPackageOperation.None に設定されます。 この値により、ドラッグ ソースがドロップ ターゲット上にドロップされても、アクションが実行されなくなります。

データ パッケージを処理する

Drop イベントは、ドロップ ターゲットの上でドラッグ ソースがリリースされた場合に発生します。 ドラッグ ソースが次のコントロールにドロップされると、.NET MAUI はデータ パッケージからのデータの取得を自動的に試行します。

次の表では、テキスト コントロールにテキスト ベースのドラッグ ソースがドロップされた場合に設定されるプロパティやどのような変換が試行されるかを示します。

コントロール プロパティ 変換
CheckBox IsChecked stringbool に変換されます。
DatePicker Date stringDateTime に変換されます。
Editor Text
Entry Text
Label Text
RadioButton IsChecked stringbool に変換されます。
Switch IsToggled stringbool に変換されます。
TimePicker Time stringTimeSpan に変換されます。

テキストと画像以外のコンテンツの場合は、データ パッケージを自分で処理する必要があります。

Drop イベントに付随する DropEventArgs クラスでは、DataPackageView 型の Data プロパティが定義されています。 このプロパティは、データ パッケージの読み取り専用バージョンを表します。

画像データまたはテキスト データを取得する

DataPackageView クラスで定義されているメソッドを使用して、Drop イベントのハンドラー内でデータ パッケージから画像データまたはテキスト データを取得できます。

DataPackageView クラスには、GetImageAsync メソッドと GetTextAsync メソッドが含まれています。 GetImageAsync メソッドは、DataPackage.Image プロパティに格納されたデータ パッケージから画像を取得し、Task<ImageSource> を返します。 同様に、GetTextAsync メソッドは、DataPackage.Text プロパティに格納されたデータ パッケージからテキストを取得し、Task<string> を返します。

次の例では、Path に対するデータ パッケージからテキストを取得する Drop イベント ハンドラーが示されています。

async void OnDrop(object sender, DropEventArgs e)
{
    string text = await e.Data.GetTextAsync();

    // Perform logic to take action based on the text value.
}

この例では、GetTextAsync メソッドを使用してデータ パッケージからテキスト データが取得されます。 その後、テキスト値に基づくアクションを実行できます。

プロパティ バッグからデータを取得する

データ パッケージの Properties コレクションにアクセスすることにより、Drop イベントのハンドラー内でデータ パッケージから任意のデータを取得できます。

DataPackageView クラスでは、DataPackagePropertySetView 型の Properties プロパティが定義されています。 DataPackagePropertySetView クラスは、Dictionary<string, object> として格納される読み取り専用のプロパティ バッグを表します。

次の例では、Rectangle に対するデータ パッケージのプロパティ バッグからデータを取得する Drop イベント ハンドラーが示されています。

void OnDrop(object sender, DropEventArgs e)
{
    Square square = (Square)e.Data.Properties["Square"];

    // Perform logic to take action based on retrieved value.
}

この例では、"Square" ディクショナリ キーを指定することにより、データ パッケージのプロパティ バッグから Square オブジェクトを取得します。 その後、取得された値に基づくアクションを実行できます。

ジェスチャの位置を取得する

ドラッグ アンド ドロップ ジェスチャが発生した位置は、GetPosition メソッドを、DragEventArgsDragStartingEventArgsDropEventArgs オブジェクトで呼び出すことによって取得できます。 GetPosition メソッドは Element? 引数を受け取り、Point? オブジェクトとして位置を返します。

void OnDragStarting(object sender, DragStartingEventArgs e)
{
    // Position relative to screen
    Point? screenPosition = e.GetPosition(null);

    // Position relative to specified element
    Point? relativeToImagePosition = e.GetPosition(image);
}

Element? 引数は、位置を取得する必要がある要素を定義します。 この引数として null 値を指定すると、GetPosition メソッドは画面に対するドラッグ または ドロップ ジェスチャの位置を定義する Point? オブジェクトを返します。