拖放

拖放是一種直覺式的方式,可在應用程式內或在 Windows 桌面上的應用程式之間傳輸資料。 拖放功能可讓使用者使用標準手勢在應用程式之間或應用程式內傳輸資料(使用手指按住並移動流覽,或使用滑鼠或手寫筆按平移)。

重要 APICanDrag 屬性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 並開啟其操作功能表會共用類似的觸控手勢;每個動作都是以按下和按住開始。 以下是系統如何區分您應用程式中支援這兩個元素的兩個動作:

  • 如果使用者按下並保留專案,並開始在500毫秒內拖曳它,則會拖曳專案,而且不會顯示操作功能表。
  • 如果使用者按下並保留,但不會在500毫秒內拖曳,則會開啟操作功能表。
  • 在操作功能表開啟之後,如果使用者嘗試拖曳專案(但不抬起手指),操作功能表就會關閉,拖曳將會啟動。

將 ListView 或 GridView 中的專案指定為資料夾

您可以將 ListViewItem 或 GridViewItem 指定為資料夾。 這特別適用於 TreeView 和 檔案總管 案例。 若要這樣做,請明確將該專案上的AllowDrop屬性設定為True。

系統會自動顯示放入資料夾與非資料夾專案的適當動畫。 您的應用程式程式碼必須繼續處理 資料夾專案上的Drop 事件(以及非資料夾專案上),才能更新資料源,並將卸除的專案新增至目標資料夾。

在 ListViews 內啟用拖放重新排序

ListView支援現用的拖曳式重新排序,其使用 API 非常類似 本文所述的 CanDrop 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

另請參閱