ドラッグ アンド ドロップ

ドラッグ アンド ドロップは、Windows デスクトップでアプリケーション内またはアプリケーション間でデータを転送するための直感的な方法です。 ドラッグ アンド ドロップを利用すると、ユーザーは、標準ジェスチャ (指で押したままパン、またはマウスやスタイラスでボタンを押したままパン) 使ってアプリケーション間やアプリケーション内でデータを転送できます。

重要な API: CanDrag プロパティAllowDrop プロパティ

ドラッグ ソース (ドラッグ ジェスチャがトリガーされたアプリケーションや領域) は、標準的なデータ形式 (テキスト、RTF、HTML、ビットマップ、ストレージ項目) やカスタム データ形式を含むことができるデータ パッケージ オブジェクトに入力することによって、転送されるデータを提供します。 ソースは、ソースがサポートする操作の種類 (コピー、移動、リンク) も示します。 ポインターが離されたときにドロップが発生します。 ドロップ ターゲット (ポインターの下にあるアプリケーションや領域) は、データ パッケージを処理し、実行される操作の種類を返します。

ドラッグ アンド ドロップを行っているとき、ドラッグ UI によって、実行されているドラッグ アンド ドロップ操作の種類が視覚的に示されます。 この視覚的なフィードバックは、ソースによって最初に提供されますが、ポインターがターゲットの上に移動したときに、ターゲットによって変更することができます。

最新のドラッグ アンド ドロップは、UWP をサポートするすべてのデバイスで利用できます。 このドラッグ アンド ドロップでは、すべての種類のアプリケーション間やアプリケーション内でデータを転送できます。こうしたアプリケーションには従来の Windows アプリも含まれますが、この記事では、最新のドラッグ アンド ドロップについては XAML API に焦点を当てています。 ドラッグ アンド ドロップを実装すると、アプリからアプリ、アプリからデスクトップ、デスクトップからアプリなど、あらゆる方向でシームレスに機能します。

アプリでドラッグ アンド ドロップを有効にする場合に必要となることの概要を次に示します。

  1. 要素に対してドラッグを有効にするには、要素の CanDrag プロパティを true に設定します。
  2. データ パッケージを作成します。 システムは画像とテキストを自動的に処理しますが、他のコンテンツの場合は 、DragStarting イベントと DropCompleted イベントを処理し、それらを使用して独自のデータ パッケージを構築する必要があります。
  3. ドロップされるコンテンツを受け取ることができるすべての要素に対して、AllowDrop プロパティを true に設定することで、ドロップを有効にします。
  4. DragOver イベントを処理して、要素が受け取ることができるドラッグ操作の種類をシステムに通知します。
  5. Drop イベントを処理して、ドロップされるコンテンツを受け取ります。

ドラッグを有効にする

要素に対してドラッグを有効にするには、要素の CanDrag プロパティを true に設定します。 これにより、要素 (およびその要素が含む要素 (ListView などのコレクションの場合)) をドラッグ可能にします。

どの要素をドラッグ可能にするかを、明確にしておいてください。 ユーザーは、アプリ内にあるすべての項目をドラッグできるようにするのではなく、画像やテキストなどの特定の項目のみをドラッグすることを必要としています。

CanDrag の設定方法を次に示します。

<Image x:Name="Image" CanDrag="True" Margin="10,292,10,0" Height="338"></Image>

UI をカスタマイズする場合 (この記事の後半で説明します) を除き、他には何もしなくてもドラッグ操作を有効にできます。 ドロップ操作には、あといくつかの手順が必要です。

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

ほとんどの場合、システムによってデータ パッケージが自動的に作成されます。 システムでは、次のコンテンツが自動的に処理されます。

  • イメージ
  • Text

その他のコンテンツについては、 DragStarting イベントと DropCompleted イベントを処理し、それらを使用して独自の DataPackage を構築する必要があります

ドロップを有効にする

次のマークアップは、XAML で AllowDrop を使って、アプリの特定の領域をドロップ操作に有効な領域として設定する方法を示しています。 ユーザーが他の場所へのドロップを試みても、ドロップすることはできません。 アプリ内のすべての領域でユーザーが項目をドロップできるようにする場合は、背景全体をドロップ先として設定します。

<Grid AllowDrop="True" DragOver="Grid_DragOver" Drop="Grid_Drop"
      Background="LightBlue" Margin="10,10,10,353">
    <TextBlock>Drop anywhere in the blue area</TextBlock>
</Grid>

DragOver イベントを処理する

DragOver イベントは、ユーザーがアプリに項目をドラッグし、まだドロップしていないときに発生します。 このハンドラーでは、AcceptedOperation プロパティを使って、アプリがサポートしている操作の種類を指定する必要があります。 最も一般的な操作はコピーです。

private void Grid_DragOver(object sender, DragEventArgs e)
{
    e.AcceptedOperation = DataPackageOperation.Copy;
}

Drop イベントを処理する

Drop イベントは、有効なドロップ領域内でユーザーが項目を放したときに発生します。 放した項目を処理するには DataView プロパティを使います。

次の例では、わかりやすくするために、ユーザーが単一の写真をドロップして直接それにアクセスしたとします。 実際には、ユーザーがさまざまな形式の複数の項目を同時にドロップすることもあります。 アプリで、ドロップされたファイルの種類とファイル数を確認することでこの状況を処理し、状況に応じてそれぞれを処理する必要があります。 また、ユーザーがアプリでサポートされていない処理を実行しようとしたときに、ユーザーに通知することを検討する必要があります。

private async void Grid_Drop(object sender, DragEventArgs e)
{
    if (e.DataView.Contains(StandardDataFormats.StorageItems))
    {
        var items = await e.DataView.GetStorageItemsAsync();
        if (items.Count > 0)
        {
            var storageFile = items[0] as StorageFile;
            var bitmapImage = new BitmapImage();
            bitmapImage.SetSource(await storageFile.OpenAsync(FileAccessMode.Read));
            // Set the image on the main page to the dropped image
            Image.Source = bitmapImage;
        }
    }
}

UI のカスタマイズ

システムでは、ドラッグ アンド ドロップ用に既定の UI が提供されています。 ただし、カスタムのキャプションやグリフを設定して UI のさまざまな部分をカスタマイズすることも、UI をまったく表示しないこともできます。 UI をカスタマイズするには、DragEventArgs.DragUIOverride プロパティを使います。

private void Grid_DragOverCustomized(object sender, DragEventArgs e)
{
    e.AcceptedOperation = DataPackageOperation.Copy;
    e.DragUIOverride.Caption = "Custom text here"; // Sets custom UI text
    // Sets a custom glyph
    e.DragUIOverride.SetContentFromBitmapImage(
        new BitmapImage(
            new Uri("ms-appx:///Assets/CustomImage.png", UriKind.RelativeOrAbsolute)));
    e.DragUIOverride.IsCaptionVisible = true; // Sets if the caption is visible
    e.DragUIOverride.IsContentVisible = true; // Sets if the dragged content is visible
    e.DragUIOverride.IsGlyphVisible = true; // Sets if the glyph is visibile
}

タッチによるドラッグが可能な項目のコンテキスト メニューを開く

タッチを使い、UIElement をドラッグして、コンテキスト メニューを開くには、類似したタッチ ジェスチャを使用します。それぞれ長押しから始まります。 アプリの要素が 2 つのアクションをサポートしている場合に、システムがそれを区別する方法を次に示します。

  • ユーザーがある項目を長押しし、500 ミリ秒以内にドラッグを開始した場合、項目はドラッグされ、コンテキスト メニューは表示されません。
  • ユーザーが長押ししてから 500 ミリ秒以内にドラッグしなかった場合には、コンテキスト メニューが開きます。
  • コンテキスト メニューが開いた後に、ユーザーが指を離すことなく、項目をドラッグしようとすると、コンテキスト メニューは閉じられ、ドラッグが開始されます。

ListView または GridView の項目をフォルダーとして指定する

ListViewItem または GridViewItem をフォルダーとして指定できます。 これは、ツリー ビューとエクスプローラーのシナリオで特に便利です。 これを行うには、その項目で AllowDrop プロパティを明示的に True に設定します。

(非フォルダー項目にではなく) フォルダーにドロップするための、適切なアニメーションが自動的に表示されます。 アプリのコードは、フォルダー項目のドロップ イベントの処理 (および非フォルダー項目の処理) を継続し、データ ソースを更新して、ドロップ先のフォルダーにドロップされた項目を追加する必要があります。

ListView 内でドラッグ アンド ドロップの並べ替えを有効にする

ListView は、この記事で説明されている CanDrop API と非常によく似た API を使用して、すぐに使用できるドラッグベースの並べ替えをサポートしています。 少なくとも、AllowDropCanReorderItems のプロパティを追加します。

詳細については、ListViewBase.CanReorderItems を参照してください。

カスタムのドラッグ アンド ドロップを実装する

UIElement クラスは、ドラッグ アンド ドロップを実装するためのほとんどの処理を自動的に実行します。 ただし必要に応じて、独自のバージョンを実装することもできます。そのためには、Windows.ApplicationModel.DataTransfer.DragDrop.Core 名前空間の API を使います。

機能 WinRT API
ドラッグを有効にする CoreDragOperation
データ パッケージを作成する DataPackage
ドラッグをシェルに渡す CoreDragOperation.StartAsync
シェルからドロップを受け取る CoreDragDropManager
ICoreDropOperationTarget

こちらもご覧ください