Hinzufügen von Drag & Drop-Gestenerkennung

Mithilfe einer Drag & Drop-Geste können Elemente und die zugehörigen Datenpakete mit einer kontinuierlichen Geste von einer Bildschirmposition an eine andere gezogen werden. Drag & Drop kann in einer einzelnen App stattfinden, oder in einer App beginnen und in einer anderen App enden.

Wichtig

Das Erkennen von Drag & Drop-Gesten wird unter iOS, Android und der universellen Windows-Plattform (UWP) unterstützt. Unter iOS ist jedoch mindestens iOS 11 erforderlich.

Die Drag-Quelle, das Element, auf dem die Drag-Geste initiiert wird, kann Daten bereitstellen, die durch Auffüllen eines Datenpaketobjekts übertragen werden. Wenn die Drag-Quelle losgelassen wird, findet das Ablegen statt. Das Drop-Ziel, das Element unter der Drag-Quelle, verarbeitet dann das Datenpaket.

Der Vorgang zum Aktivieren von Drag & Drop in einer Anwendung läuft wie folgt ab:

  1. Aktivieren Sie Drag für ein Element, indem Sie dessen GestureRecognizers-Sammlung ein DragGestureRecognizer-Objekt hinzufügen. Weitere Informationen finden Sie unter Aktivieren von Drag.
  2. [optional] Erstellen Sie ein Datenpaket. Xamarin.Forms füllt das Datenpaket für Bild- und Textsteuerelemente automatisch auf, aber für andere Inhalte müssen Sie ein eigenes Datenpaket erstellen. Weitere Informationen finden Sie unter Erstellen eines Datenpakets.
  3. Aktivieren Sie Ablegen für ein Element, indem Sie dessen GestureRecognizers-Sammlung ein DropGestureRecognizer-Objekt hinzufügen. Weitere Informationen finden Sie unter Aktivieren von Drop.
  4. [optional] Verarbeiten Sie das DropGestureRecognizer.DragOver-Ereignis, um den Vorgangstyp anzugeben, den das Drop-Ziel zulässt. Weitere Informationen finden Sie unter Verarbeiten des DragOver-Ereignisses.
  5. [optional] Verarbeiten Sie das Datenpaket, um den gelöschten Inhalt zu empfangen. Xamarin.Forms ruft automatisch Bild- und Textdaten aus dem Datenpaket ab, aber für andere Inhalte müssen Sie das Datenpaket verarbeiten. Weitere Informationen finden Sie unter Verarbeiten des Datenpakets.

Hinweis

Das Ziehen von Elementen in eine und aus einer CollectionView wird derzeit nicht unterstützt.

Aktivieren von Drag

In Xamarin.Forms sorgt die DragGestureRecognizer-Klasse für die Erkennung der Ziehgeste. Diese Klasse definiert die folgenden Eigenschaften:

  • CanDrag vom Typ bool gibt an, ob das Element, dem die Gestenerkennung angefügt ist, eine Drag-Quelle sein kann. Der Standardwert dieser Eigenschaft ist true.
  • DragStartingCommand vom Typ ICommand, der ausgeführt wird, sobald eine Drag-Geste erkannt wird.
  • DragStartingCommandParameter, vom Typ object: Parameter, der an den DragStartingCommand übergeben wird.
  • DropCompletedCommand vom Typ ICommand, der ausgeführt wird, sobald die Drag-Quelle abgelegt wird.
  • DropCompletedCommandParameter, vom Typ object: Parameter, der an den DropCompletedCommand übergeben wird.

Diese Eigenschaften werden von BindableProperty-Objekten unterstützt, was bedeutet, dass sie Ziele von Datenbindungen sein können und formatiert werden können.

Die DragGestureRecognizer-Klasse definiert auch DragStarting- und DropCompleted-Ereignisse, die ausgelöst werden, wenn die CanDrag-Eigenschaft true ist. Wenn ein DragGestureRecognizer-Objekt eine Drag-Geste erkennt, führt es den DragStartingCommand aus und ruft das DragStarting-Ereignis auf. Wenn dann das DragGestureRecognizer-Objekt die Ausführung einer Drop-Geste erkennt, führt es den DropCompletedCommand aus und ruft das DropCompleted-Ereignis auf.

Das DragStartingEventArgs-Objekt, das das DragStarting-Ereignis begleitet, definiert folgende Eigenschaften:

  • Handled vom Typ bool gibt an, ob der Ereignishandler das Ereignis verarbeitet hat oder ob Xamarin.Forms seine eigene Verarbeitung fortsetzen sollte.
  • Cancel vom Typ bool gibt an, ob das Ereignis abgebrochen werden sollte.
  • Data vom Typ DataPackage gibt das Datenpaket an, das die Drag-Quelle begleitet. Dies ist eine schreibgeschützte Eigenschaft.

Das folgende XAML-Beispiel zeigt einen DragGestureRecognizer, der einem Image angefügt ist:

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

In diesem Beispiel kann eine Ziehgeste auf dem Image initiiert werden.

Tipp

Unter iOS, Android und UWP wird eine Ziehgeste mit einem langen Drücken gefolgt von einem Ziehen initiiert.

Erstellen eines Datenpakets

Xamarin.Forms erstellt beim Initiieren eines Ziehvorgang für die folgenden Steuerelemente automatisch ein Datenpaket für Sie:

In der folgenden Tabelle sind die Eigenschaften aufgeführt, die beim Initiieren eines Ziehens für ein Textsteuerelement gelesen, und alle Konvertierungen, die versucht werden:

Control Eigenschaft Konvertierung
CheckBox IsChecked bool umgewandelt in ein string.
DatePicker Date DateTime umgewandelt in ein string.
Editor Text
Entry Text
Label Text
RadioButton IsChecked bool umgewandelt in ein string.
Switch IsToggled bool umgewandelt in ein string.
TimePicker Time TimeSpan umgewandelt in ein string.

Für andere Inhalte als Text und Bilder müssen Sie selbst ein Datenpaket erstellen.

Datenpakete werden von der DataPackage-Klasse dargestellt, die die folgenden Eigenschaften definiert:

  • Properties vom Typ DataPackagePropertySet, eine Sammlung von Eigenschaften, die die im DataPackage enthaltenen Daten umfassen. Diese Eigenschaft ist schreibgeschützt.
  • Image vom Typ ImageSource, das im DataPackage enthaltene Bild.
  • Text vom Typ string, der im DataPackage enthaltene Text.
  • View vom Typ DataPackageView, eine schreibgeschützte Version des DataPackage.

Die DataPackagePropertySet-Klasse stellt eine als Dictionary<string,object> gespeicherte Eigenschaftensammlung dar. Weitere Informationen zur DataPackageView-Klasse finden Sie unter Verarbeiten des Datenpakets.

Speichern von Bild- oder Textdaten

Bild- oder Textdaten können mit einer Ziehquelle verknüpft werden, indem die Daten in der DataPackage.Image- oder DataPackage.Text-Eigenschaft gespeichert werden. Dies kann im Handler für das DragStarting-Ereignis durchgeführt werden.

Das folgende XAML-Beispiel zeigt einen DragGestureRecognizer, der einen Handler für das DragStarting-Ereignis registriert:

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

In diesem Beispiel wird der DragGestureRecognizer einem Path-Objekt angefügt. Das DragStarting-Ereignis wird ausgelöst, wenn eine Ziehgeste im Path erkannt wird, wodurch der OnDragStarting-Ereignishandler ausgeführt wird:

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

Das DragStartingEventArgs-Objekt, das das DragStarting-Ereignis begleitet, hat eine Data-Eigenschaft vom Typ DataPackage. In diesem Beispiel wird die Text-Eigenschaft des DataPackage-Objekts auf einen string festgelegt. Auf das DataPackage kann dann beim Ablegen zugegriffen werden, um den string abzurufen.

Speichern von Daten in der Eigenschaftensammlung

Alle Daten einschließlich Bilder und Text können mit einer Drag-Quelle verknüpft werden, indem die Daten in der DataPackage.Properties-Sammlung gespeichert werden. Dies kann im Handler für das DragStarting-Ereignis durchgeführt werden.

Das folgende XAML-Beispiel zeigt einen DragGestureRecognizer, der einen Handler für das DragStarting-Ereignis registriert:

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

In diesem Beispiel wird der DragGestureRecognizer einem Rectangle-Objekt angefügt. Das DragStarting-Ereignis wird ausgelöst, wenn eine Ziehgeste im Rectangle erkannt wird, wodurch der OnDragStarting-Ereignishandler ausgeführt wird:

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));
}

Das DragStartingEventArgs-Objekt, das das DragStarting-Ereignis begleitet, hat eine Data-Eigenschaft vom Typ DataPackage. Die Properties-Sammlung des DataPackage-Objekts, eine Dictionary<string, object>-Sammlung, kann so geändert werden, dass alle erforderlichen Daten gespeichert werden. In diesem Beispiel wird das Properties-Wörterbuch so geändert, dass ein Square-Objekt, das die Größe des Rectangle darstellt, mit einem „Square“-Schlüssel gespeichert wird.

Aktivieren des Ablegens

In Xamarin.Forms sorgt die DropGestureRecognizer-Klasse für die Erkennung der Ablegegeste. Diese Klasse definiert die folgenden Eigenschaften:

  • AllowDrop vom Typ bool gibt an, ob das Element, dem die Gestenerkennung angefügt ist, ein Ablageziel sein kann. Der Standardwert dieser Eigenschaft ist true.
  • DragOverCommand vom Typ ICommand, der ausgeführt wird, sobald die Drag-Quelle über das Ablageziel gezogen wird.
  • DragOverCommandParameter, vom Typ object: Parameter, der an den DragOverCommand übergeben wird.
  • DragLeaveCommand vom Typ ICommand, der ausgeführt wird, sobald die Drag-Quelle vom Ablageziel gezogen wird.
  • DragLeaveCommandParameter, vom Typ object: Parameter, der an den DragLeaveCommand übergeben wird.
  • DropCommand vom Typ ICommand, der ausgeführt wird, sobald die Drag-Quelle über dem Ablageziel abgelegt wird.
  • DropCommandParameter, vom Typ object: Parameter, der an den DropCommand übergeben wird.

Diese Eigenschaften werden von BindableProperty-Objekten unterstützt, was bedeutet, dass sie Ziele von Datenbindungen sein können und formatiert werden können.

Die DropGestureRecognizer-Klasse definiert auch DragOver-, DragLeave- und Drop-Ereignisse, die ausgelöst werden, wenn die AllowDrop-Eigenschaft true ist. Wenn ein DropGestureRecognizer eine Drag-Quelle über dem Ablageziel erkennt, führt er den DragOverCommand aus und ruft das DragOver-Ereignis auf. Wenn dann die Drag-Quelle vom Ablageziel gezogen wird, führt DropGestureRecognizerDragLeaveCommand aus und ruft das DragLeave-Ereignis auf. Wenn ein DropGestureRecognizer schließlich eine Drag-Quelle über dem Ablageziel erkennt, führt er den DropCommand aus und ruft das Drop-Ereignis auf.

Die DragEventArgs-Klasse, die die DragOver- und DragLeave-Ereignisse begleitet, definiert folgende Eigenschaften:

  • Data vom Typ DataPackage, wo die mit der Drag-Quelle verknüpften Daten enthalten sind. Diese Eigenschaft ist schreibgeschützt.
  • AcceptedOperation vom Typ DataPackageOperation, womit angegeben wird, welche Vorgänge das Ablageziel zulässt.

Informationen zur DataPackageOperation-Enumeration finden Sie unter Verarbeiten des DragOver-Ereignisses.

Die DropEventArgs-Klasse, die das Drop-Ereignis begleitet, definiert folgende Eigenschaften:

  • Data vom Typ DataPackageView, eine schreibgeschützte Version des Datenpakets.
  • Handled vom Typ bool gibt an, ob der Ereignishandler das Ereignis verarbeitet hat oder ob Xamarin.Forms seine eigene Verarbeitung fortsetzen sollte.

Das folgende XAML-Beispiel zeigt einen DropGestureRecognizer, der einem Image angefügt ist:

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

Wenn in diesem Beispiel eine Ziehquelle auf dem Image-Ablageziel abgelegt wird, wird die Ziehquelle in das Ablageziel kopiert, sofern die Ziehquelle eine ImageSource ist. Dies geschieht, weil Xamarin.Forms gezogene Bilder und Texte automatisch in kompatible Ablageziele kopiert.

Behandeln des DragOver-Ereignisses

Das DropGestureRecognizer.DragOver-Ereignis kann optional verarbeitet werden, um anzugeben, welche Typen von Vorgängen das Ablageziel zulässt. Zu diesem Zweck kann die AcceptedOperation-Eigenschaft des Typs DataPackageOperation des DragEventArgs-Objekts festgelegt werden, das das DragOver-Ereignis begleitet.

Die DataPackageOperation-Enumeration definiert die folgenden Members:

  • None gibt an, dass keine Aktion ausgeführt wird.
  • Copy gibt an, dass der Inhalt der Drag-Quelle in das Ablageziel kopiert wird.

Wichtig

Wenn ein DragEventArgs-Objekt erstellt wird, wird die Eigenschaft AcceptedOperation standardmäßig auf DataPackageOperation.Copy gesetzt.

Das folgende XAML-Beispiel zeigt einen DropGestureRecognizer, der einen Handler für das DragOver-Ereignis registriert:

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

In diesem Beispiel wird der DropGestureRecognizer einem Image-Objekt angefügt. Das DragOver-Ereignis wird ausgelöst, wenn eine Ziehquelle über das Ablageziel gezogen wird, aber noch nicht gelöscht wurde, wodurch der OnDragOver-Ereignishandler ausgeführt wird:

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

In diesem Beispiel wird die AcceptedOperation-Eigenschaft des DragEventArgs-Objekts auf DataPackageOperation.None festgelegt. Dadurch wird sichergestellt, dass keine Aktion ausgeführt wird, wenn eine Ziehquelle über dem Ablageziel abgelegt wird.

Verarbeiten des Datenpakets

Das Drop-Ereignis wird ausgelöst, wenn eine Ziehquelle über einem Ablageziel freigegeben wird. In diesem Fall wird Xamarin.Forms automatisch versuchen, Daten aus dem Datenpaket abzurufen, wenn eine Ziehquelle auf den folgenden Steuerelementen abgelegt wird:

In der folgenden Tabelle sind die Eigenschaften aufgeführt, die beim Ablegen einer textbasierten Ziehquelle auf einem Textsteuerelement festgelegt, und alle Konvertierungen, die versucht werden:

Control Eigenschaft Konvertierung
CheckBox IsChecked string wird in bool konvertiert.
DatePicker Date string wird in DateTime konvertiert.
Editor Text
Entry Text
Label Text
RadioButton IsChecked string wird in bool konvertiert.
Switch IsToggled string wird in bool konvertiert.
TimePicker Time string wird in TimeSpan konvertiert.

Für andere Inhalte als Text und Bilder müssen Sie das Datenpaket selbst verarbeiten.

Die DropEventArgs-Klasse, die das Drop-Ereignis begleitet, definiert eine Data-Eigenschaft vom Typ DataPackageView. Diese Eigenschaft stellt eine schreibgeschützte Version des Datenpakets dar.

Abrufen von Bild- oder Textdaten

Bild- oder Textdaten können mithilfe von Methoden, die in der DataPackageView-Klasse definiert sind, aus einem Datenpaket im Handler für das Drop-Ereignis abgerufen werden.

Die DataPackageView-Klasse beinhaltet die GetImageAsync- und die GetTextAsync-Methode. Die GetImageAsync-Methode ruft ein Bild aus dem Datenpaket ab, das in der DataPackage.Image-Eigenschaft gespeichert wurde, und gibt Task<ImageSource> zurück. Ebenso ruft die GetTextAsync-Methode einen Text aus dem Datenpaket ab, der in der DataPackage.Text-Eigenschaft gespeichert wurde, und gibt Task<string> zurück.

Das folgende Beispiel zeigt einen Drop-Ereignishandler, der aus dem Datenpaket Text für einen Path abruft:

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

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

In diesem Beispiel werden Textdaten mithilfe der GetTextAsync-Methode aus dem Datenpaket abgerufen. Dann kann eine Aktion durchgeführt werden, die auf dem Textwert basiert.

Abrufen von Daten aus der Eigenschaftensammlung

Alle Daten können für das Drop-Ereignis aus einem Datenpaket im Handler abgerufen werden, indem auf die Properties-Sammlung des Datenpakets zugegriffen wird.

Die DataPackageView-Klasse definiert eine Properties-Eigenschaft vom Typ DataPackagePropertySetView. Die DataPackagePropertySetView-Klasse stellt eine als Dictionary<string, object> gespeicherte schreibgeschützte Eigenschaftensammlung dar.

Das folgende Beispiel zeigt einen Drop-Ereignishandler, der aus der Eigenschaftensammlung eines Datenpakets Daten für ein Rectangle abruft:

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

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

In diesem Beispiel wird durch Angabe des Wörterbuchschlüssels „Square“ das Square-Objekt aus der Eigenschaftensammlung des Datenpakets abgerufen. Dann kann eine Aktion durchgeführt werden, die auf dem abgerufenen Wert basiert.