ドラッグ アンド ドロップ

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

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

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

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

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

アプリでドラッグ アンド ドロップを有効にするために必要な操作の概要を次に示します。

  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 をカスタマイズする (この記事の後半で説明します) 場合を除き、ドラッグを可能にするために他の作業を行う必要はありません。 ドロップには、さらにいくつかの手順が必要です。

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

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

  • 画像
  • テキスト

他のコンテンツについては、DragStarting イベントと DropCompleted イベントを手動で処理し、これらを使って独自の DataPackage を作成する必要があります。

ドロップを有効にする

次のマークアップは、 AllowDrop プロパティを使用して、アプリの領域がドラッグされたアイテムの有効なドロップ ターゲットであることを指定する方法を示しています (指定した領域は null の背景を持たなければならず、ポインター入力を受け取ることができなければならず、指定した領域以外の場所にアイテムをドロップすることはできません)。

Note

通常、UI 要素の背景は既定で null です。 ユーザーがアプリ内の任意の場所にアイテムをドロップできるようにする場合、アプリの背景を null にすることはできません (背景を表示しない場合は Background="Transparent" 設定します)。

<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 プロパティを使用して、アプリでサポートされる操作の種類を指定する必要があります。 Copy が最も一般的です。

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

Drop イベントを処理する

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

次の例ではわかりやすくするために、ユーザーが 1 つの写真をドロップしたことを前提とし、それに直接アクセスします。 実際には、ユーザーはさまざまな形式の複数の項目を同時にドロップできます。 アプリは、ドロップされたファイルの種類と数をチェックしてこの可能性に対処し、それに応じてそれぞれを処理する必要があります。 また、アプリでサポートされていない操作を行おうとしている場合は、ユーザーに通知することも検討する必要があります。

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 をフォルダーとして指定できます。 これは、TreeView とエクスプローラーのシナリオで特に便利です。 これを行うには、その項目で AllowDrop プロパティを True に明示的に設定します。

フォルダー項目にドロップする場合とフォルダー以外の項目にドロップする場合の適切なアニメーションが、システムによって自動的に表示されます。 データ ソースを更新し、ドロップした項目をターゲット フォルダーに追加するには、アプリ コードでフォルダー項目 (およびフォルダー以外の項目) の Drop イベントを引き続き処理する必要があります。

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

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

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

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

UIElement クラスは、ドラッグ アンド ドロップを実装するほとんどの作業を自動的に行います。 ただし、必要に応じて、以下の API を使用して独自のバージョンを実装できます。

機能 WinAppSDK API
Microsoft.UI.Input.DragDrop 名前空間
UWP API
Windows.Applicationmodel.DataTransfer.DragDrop.Core 名前空間
DragPrimitive DragOperation CoreDragOperation
データ パッケージを作成する DataPackage 同じ
ハンドオフしてシェルにドラッグする DragOperation.StartAsync CoreDragOperation.StartAsync
シェルからドロップを受け取る DragDropManager.TargetRequested
ICoreDropOperationTarget
CoreDragDropManager.TargetRequested
ICoreDropOperationTarget

関連項目