新增拖放手勢辨識器

Download Sample 下載範例

拖放手勢可讓專案及其相關聯的數據套件使用連續手勢,從螢幕上的一個位置拖曳到另一個位置。 拖放可以在單一應用程式中進行,或者它可以在一個應用程式中啟動,並結束於另一個應用程式。

重要

iOS、Android 和 通用 Windows 平台 (UWP) 支援拖放手勢的辨識。 不過,在 iOS 上,需要 iOS 11 的最低平臺。

拖曳來源,這是拖曳手勢起始的專案,可以填入數據封裝物件來提供要傳輸的數據。 放開拖曳來源時,就會發生卸除。 置放目標,也就是拖曳來源下的專案,然後處理數據封裝。

在應用程式中啟用拖放的程式如下:

  1. 將物件加入 DragGestureRecognizer 至其 GestureRecognizers 集合,以啟用拖曳專案。 如需詳細資訊,請參閱 啟用拖曳
  2. [選擇性]建置數據封裝。 Xamarin.Forms 會自動填入影像和文字控件的數據套件,但對於其他內容,您必須建構自己的數據套件。 如需詳細資訊,請參閱 建置數據封裝
  3. 藉由加入 DropGestureRecognizer 物件的 GestureRecognizers 集合來啟用專案卸除。 如需詳細資訊,請參閱 啟用卸除
  4. [選擇性] DropGestureRecognizer.DragOver 處理 事件,以指出置放目標所允許的作業類型。 如需詳細資訊,請參閱 處理 DragOver 事件
  5. [選擇性]處理數據封裝以接收已卸除的內容。 Xamarin.Forms 會自動從數據封裝擷取影像和文字數據,但對於其他內容,您必須處理數據封裝。 如需詳細資訊,請參閱 處理數據封裝

注意

目前不支援從 CollectionView 中拖曳專案。

啟用拖曳

在 中 Xamarin.Forms,拖曳手勢辨識是由 DragGestureRecognizer 類別提供。 這個類別會定義下列屬性:

  • CanDragbool別為 的 ,指出筆勢辨識器所附加的專案是否可以是拖曳來源。 此屬性的預設值為 true
  • DragStartingCommand,屬於 類型 ICommand,這是第一次辨識拖曳手勢時所執行的。
  • DragStartingCommandParameter,屬於 object 類型,這是傳遞至 DragStartingCommand 的參數。
  • DropCompletedCommand型別為 ICommand的 ,會在卸除拖曳來源時執行。
  • DropCompletedCommandParameter,屬於 object 類型,這是傳遞至 DropCompletedCommand 的參數。

這些屬性是由 BindableProperty 物件所支援,這表示這些屬性可以是數據系結的目標,並設定樣式。

類別 DragGestureRecognizer 也會定義 DragStartingDropCompleted 事件,前提是 CanDrag 屬性為 trueDragGestureRecognizer當物件偵測到拖曳手勢時,它會執行 DragStartingCommand 並叫用 DragStarting 事件。 然後,當對象偵測到卸除手勢完成時 DragGestureRecognizer ,它會執行 DropCompletedCommand 並叫用 DropCompleted 事件。

事件 DragStartingEventArgs 隨附 DragStarting 的物件會定義下列屬性:

  • Handledbool別為 的 ,表示事件處理程式是否已處理事件,還是應該 Xamarin.Forms 繼續自己的處理。
  • Cancelbool別為 的 ,表示是否應該取消事件。
  • DataDataPackage別為 的 ,表示拖曳來源隨附的數據套件。 這是一個唯讀屬性。

下列 XAML 範例顯示 DragGestureRecognizer 附加至 Image的 :

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

在此範例中,可以在上 Image起始拖曳手勢。

提示

在iOS、Android和UWP上,拖曳手勢會以長按後再拖曳來起始。

如需使用 DragGestureRecognizer 命令的範例,請參閱 範例

建置數據套件

Xamarin.Forms 會在起始拖曳時,自動為您建置數據封裝,以進行下列控件:

下表顯示讀取的屬性,以及在文字控件上起始拖曳時嘗試的任何轉換:

控制 屬性 轉換
CheckBox IsChecked bool 轉換成 string
DatePicker Date DateTime 轉換成 string
Editor Text
Entry Text
Label Text
RadioButton IsChecked bool 轉換成 string
Switch IsToggled bool 轉換成 string
TimePicker Time TimeSpan 轉換成 string

針對文字和影像以外的內容,您必須自行建置數據套件。

資料封裝是由 DataPackage 類別表示,其定義下列屬性:

  • PropertiesDataPackagePropertySet別為 的 ,這是屬性的集合,組成 中包含的 DataPackage數據。 此屬性是唯讀屬性。
  • Image型別為 ImageSource,這是 包含在 中的 DataPackage影像。
  • Text型別為 string,這是 包含在 中的 DataPackage文字。
  • ViewDataPackageView別為 ,這是 的 DataPackage唯讀版本。

類別 DataPackagePropertySet 代表儲存為 Dictionary<string,object>的屬性包。 如需 類別 DataPackageView 的相關信息,請參閱 處理數據封裝

儲存影像或文字數據

影像或文字數據可以藉由將數據儲存在 或 DataPackage.Text 屬性中DataPackage.Image,來與拖曳來源產生關聯。 這可以在事件的處理程式 DragStarting 中完成。

下列 XAML 範例顯示 DragGestureRecognizer 註冊 事件的處理程式 DragStarting

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

在此範例中,會 DragGestureRecognizer 附加至 Path 物件。 在 DragStartingPath偵測到拖曳手勢時,就會引發 事件,它會執行 OnDragStarting 事件處理程式:

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

事件 DragStartingEventArgs 隨附 DragStarting 的物件具有 Data 類型的 DataPackage屬性。 在這裡範例中, Text 物件的屬性 DataPackage 會設定為 stringDataPackage接著可以在卸除時存取 ,以擷string取 。

將資料儲存在屬性包中

任何數據,包括影像和文字,都可以藉由將數據儲存在集合中 DataPackage.Properties ,與拖曳來源產生關聯。 這可以在事件的處理程式 DragStarting 中完成。

下列 XAML 範例顯示 DragGestureRecognizer 註冊 事件的處理程式 DragStarting

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

在此範例中,會 DragGestureRecognizer 附加至 Rectangle 物件。 在 DragStartingRectangle偵測到拖曳手勢時,就會引發 事件,它會執行 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));
}

事件 DragStartingEventArgs 隨附 DragStarting 的物件具有 Data 類型的 DataPackage屬性。 物件的 Properties 集合 DataPackage ,這是集合 Dictionary<string, object> ,可以修改以儲存任何必要的數據。 在此範例中 Properties ,字典會修改為儲存 Square 物件,該物件代表 對 “Square” 索引鍵的大小 Rectangle

啟用卸除

在 中 Xamarin.Forms,卸除手勢辨識是由 DropGestureRecognizer 類別提供。 這個類別會定義下列屬性:

  • AllowDropbool別為 的 ,指出筆勢辨識器所附加的專案是否可以是置放目標。 此屬性的預設值為 true
  • DragOverCommandICommand別為 的 ,會在拖曳來源拖曳到置放目標上方時執行。
  • DragOverCommandParameter,屬於 object 類型,這是傳遞至 DragOverCommand 的參數。
  • DragLeaveCommand類型 ICommand為 ,會在拖曳來源從置放目標拖曳時執行。
  • DragLeaveCommandParameter,屬於 object 類型,這是傳遞至 DragLeaveCommand 的參數。
  • DropCommandICommand別為 的 ,會在拖曳來源卸除至置放目標時執行。
  • DropCommandParameter,屬於 object 類型,這是傳遞至 DropCommand 的參數。

這些屬性是由 BindableProperty 物件所支援,這表示這些屬性可以是數據系結的目標,並設定樣式。

類別 DropGestureRecognizer 也會定義 DragOverDragLeave、 和 Drop 事件,前提是 AllowDrop 屬性為 trueDropGestureRecognizer當 辨識拖曳來源到置放目標上方時,它會執行 DragOverCommand 並叫用 DragOver 事件。 然後,如果拖曳來源從置放目標拖曳,則會 DropGestureRecognizer 執行 DragLeaveCommand 並叫用 DragLeave 事件。 最後,當 辨識置放目標上的置放手勢時 DropGestureRecognizer ,它會執行 DropCommand 並叫用 Drop 事件。

DragEventArgsDragLeave 事件隨附類別 DragOver 會定義下列屬性:

  • DataDataPackage別為 的 ,其中包含與拖曳來源相關聯的數據。 這個屬性是唯讀的。
  • AcceptedOperationDataPackageOperation別為 的 ,指定卸除目標允許的作業。

如需列舉的相關信息 DataPackageOperation ,請參閱 處理 DragOver 事件

事件 DropEventArgs 隨附的 Drop 類別會定義下列屬性:

  • DataDataPackageView別為 ,這是數據封裝的唯讀版本。
  • Handledbool別為 的 ,表示事件處理程式是否已處理事件,還是應該 Xamarin.Forms 繼續自己的處理。

下列 XAML 範例顯示 DropGestureRecognizer 附加至 Image的 :

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

在此範例中,當拖曳來源在置放目標上 Image 卸除時,只要拖曳來源是 ImageSource,拖曳來源就會複製到置放目標。 Xamarin.Forms這是因為自動將拖曳的影像和文字複製到相容的置放目標。

如需使用 DropGestureRecognizer 命令的範例,請參閱 範例

處理 DragOver 事件

DropGestureRecognizer.DragOver您可以選擇性地處理事件,以指出卸除目標允許的作業類型。 若要達成此目的,可以藉由設定 AcceptedOperation 事件隨附DragOver之 物件的 屬性,類型DataPackageOperationDragEventArgs為 。

DataPackageOperation 列舉會定義下列成員:

  • None,表示不會執行任何動作。
  • Copy,表示將拖曳來源內容複製到置放目標。

重要

DragEventArgs建立物件時,AcceptedOperation屬性預設為 DataPackageOperation.Copy

下列 XAML 範例顯示 DropGestureRecognizer 註冊 事件的處理程式 DragOver

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

在此範例中,會 DropGestureRecognizer 附加至 Image 物件。 當 DragOver 拖曳來源拖曳到置放目標上,但尚未卸除時,就會引發事件,這會執行 OnDragOver 事件處理程式:

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

在這裡範例中, AcceptedOperation 物件的屬性 DragEventArgs 會設定為 DataPackageOperation.None。 這可確保當拖曳來源卸除至置放目標時,不會採取任何動作。

處理數據套件

Drop 拖曳來源放開至置放目標時,就會引發事件。 當發生這種情況時,當拖曳來源卸除至下列控件時, Xamarin.Forms 會自動嘗試從數據封裝擷取數據:

下表顯示設定的屬性,以及在文字控件上卸除以文字為基礎的拖曳來源時,所嘗試的任何轉換:

控制 屬性 轉換
CheckBox IsChecked string 轉換 bool成 。
DatePicker Date string 轉換 DateTime成 。
Editor Text
Entry Text
Label Text
RadioButton IsChecked string 轉換 bool成 。
Switch IsToggled string 轉換 bool成 。
TimePicker Time string 轉換 TimeSpan成 。

針對文字和影像以外的內容,您必須自行處理數據封裝。

事件 DropEventArgs 隨附的 Drop 類別會 Data 定義 型別 DataPackageView的屬性。 這個屬性代表數據封裝的唯讀版本。

擷取影像或文字數據

您可以使用 類別中DataPackageView定義的方法,從 事件處理程式Drop中的數據封裝擷取影像或文字數據。

類別 DataPackageView 包含 GetImageAsyncGetTextAsync 方法。 方法 GetImageAsync 會從儲存在 DataPackage.Image 屬性中的數據封裝擷取映像,並傳 Task<ImageSource>回 。 同樣地, GetTextAsync 方法會從儲存在 DataPackage.Text 屬性中的數據封裝擷取文字,並傳 Task<string>回 。

下列範例顯示 Drop 從 資料封裝擷取文字的 Path事件處理程式:

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中的數據封裝擷取任何數據。

類別 DataPackageViewProperties 定義 型別 DataPackagePropertySetView的屬性。 類別 DataPackagePropertySetView 代表儲存為 Dictionary<string, object>的唯讀屬性包。

下列範例顯示 Drop 事件處理程式,從 的數據封裝 Rectangle屬性包擷取數據:

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

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

在此範例中, Square 物件會藉由指定 「Square」 字典索引鍵,從數據封裝的屬性包擷取。 接著可以採取以擷取值為基礎的動作。