Drag and Drop mit ListBox-Elementen

Wenn Sie ein Abonnement des Magazins 'DATENBANKENTWICKLER' besitzen, können Sie sich anmelden und den kompletten Artikel lesen.
Anderenfalls können Sie das Abonnement hier im Shop erwerben.

Drag and Drop mit ListBox-Elementen

Im Artikel Drag and Drop-Grundlagen haben wir uns die grundlegenden Techniken für die Implementierung von Drag and Drop-Funktionen in WPF-Benutzeroberflächen angesehen. Nun gehen wir einen Schritt weiter und wollen Drag and Drop für das Fenster namens Versendungen unserer Beispielanwendung Bestellverwaltung umsetzen. Hier geht es dann nicht nur um einfaches Bewegen von Elementen per Maus, sondern auch um die Anpassung der dahinter stehenden Daten beziehungsweise Tabellen.

Wozu braucht man aber Drag and Drop so dringend? In der Tat lassen sich die meisten Tätigkeiten, die Sie damit ausführen können, auch auf andere Weise realisieren. Allerdings ist Drag and Drop und somit das einfache Ziehen von Elementen der Benutzeroberfläche mit der Maus doch ein sehr intuitiver Weg, um Aktionen durchzuführen. Ein Beispiel sind die beiden Listenfelder aus dem Artikel m:n-Beziehung mit Listenfeld (siehe Bild 1). Im Artikel haben wir Schaltflächen bereitgestellt, mit denen ein oder alle Artikel von einem Listenfeld zum anderen übertragen werden können. Nun wollen wir uns weiter vortasten und Drag and Drop-Funktionalität zu diesem Fenster hinzufügen. Zuvor schauen wir uns das jedoch an einigen grundlegenden Beispielen an.

Drag and Drop mit Listenfeldern

Nun schauen wir uns an, wie wir Drag and Drop in unser Beispiel mit den Versendungen einbauen. In der Beispielanwendung Bestellverwaltung_SQLite fügen wir dazu eine neue Window-Klasse namens Versendungen_DragDrop hinzu und kopieren den XAML-Code der Klasse Versendungen dort hinein. Passen Sie danach das Window-Element so an, dass die Klasse Bestellverwaltung.Versendungen_DragDrop referenziert wird und der Titel des Fensters angepasst ist:

<Window x:Class="Bestellverwaltung.Versendungen_DragDrop"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:local="clr-namespace:Bestellverwaltung"
         mc:Ignorable="d"
         Title="Versendungen Drag and Drop" Height="300" Width="400">

Dann kopieren Sie auch den Code der Code behind-Klasse von Versendungen.xaml.cs in Versendungen_DragDrop.xaml.cs. Ändern Sie hier zunächst in der folgenden Zeile Versendungen in Versendungen_DragDrop:

public partial class Versendungen_DragDrop : Window, INotifyPropertyChanged {

Der gleiche Schritt ist auch nochmal in der ersten Zeile der Konstruktor-Methode nötig:

public Versendungen_DragDrop() {

Danach können wir die Funktionen für das Drag and Drop hinzufügen.

Drag and Drop-Vorgang starten

Wir beginnen mit dem linken ListBox-Element. Hier legen wir gar nicht erst die Methode für das Ereignis MouseDown an, von dem wir dank der Experimente im Artikel Drag and Drop-Grundlagen schon wissen, dass es nicht feuert. Stattdessen legen wir direkt das entsprechende Tunneling-Ereignis PreviewMouseDown an:

<ListBox x:Name="lstAusgewaehlteKunden" Grid.Column="0" Grid.Row="1" Margin="5"
     ItemsSource="{Binding AusgewaehlteKunden}"
     DisplayMemberPath="Nachname"
     SelectedValuePath="ID" MouseDoubleClick="lstAusgewaehlteKunden_MouseDoubleClick" PreviewMouseDown="lstAusgewaehlteKunden_PreviewMouseDown"/>

Dafür hinterlegen wir nun die folgende Ereignismethode:

private void lstAusgewaehlteKunden_PreviewMouseDown(object sender, MouseButtonEventArgs e) {
     if (e.LeftButton == MouseButtonState.Pressed) {
         DragDrop.DoDragDrop(lstAusgewaehlteKunden, lstAusgewaehlteKunden.SelectedItem, DragDropEffects.Copy);
     }
}

Wenn wir die Anwendung nun starten, das Fenster Versendungen_DragDrop aufrufen und einen der Einträge der linken List­Box ziehen wollen, erhalten wir den Fehler aus Bild 2.

Fehler beim Versuch, ein Element aus der linken ListBox zu ziehen

Bild 1: Fehler beim Versuch, ein Element aus der linken ListBox zu ziehen

Da der Fehler nicht direkt an Ort und Stelle gemeldet wird, müssen wir eine Fehlerbehandlung hinzufügen:

private void lstAusgewaehlteKunden_PreviewMouseDown(object sender, MouseButtonEventArgs e) {
     try {
         if (e.LeftButton == MouseButtonState.Pressed) {
             DragDrop.DoDragDrop(lstAusgewaehlteKunden, lstAusgewaehlteKunden.SelectedItem, DragDropEffects.Copy);
         }
     }
     catch (System.Exception ex) {
         MessageBox.Show(ex.Message);
         throw;
     }
}

Dies liefert dann die Meldung aus Bild 3. Offensichtlich versuchen wir auf irgendeine Weise, ein Element des Typs Null zu ziehen. Welches das ist, erfahren wir per Debugging.

Der gleiche Fehler, diesmal mit Fehlerbehandlung

Bild 2: Der gleiche Fehler, diesmal mit Fehlerbehandlung

Dazu setzen wir einen Haltepunkt in der ersten Zeile der Methode lstAusgewaehlteKunden_PreviewMouseDown und schauen uns den Inhalt der Parameter der Methode DragDrop.DoDragDrop an. Hier erfahren wir, dass die SelectedItem-Eigenschaft des ListBox-Elements den Wert null liefert (siehe Bild 4).

Debugging der fehlerhaften Stelle

Bild 3: Debugging der fehlerhaften Stelle

Wir müssen also offensichtlich einen ganz anderen Weg wählen, um beim Herunterdrücken der Maustaste Zugriff auf das dabei überfahrene Element zu bekommen. Dabei nutzen wir eine kleine Hilfsklasse, um das zu verschiebende Element zwischenzuspeichern:

public class DragDropData {
     public object ActualData { get; set; }
}

Dieses soll in der Eigenschaft ActualData das zu verschiebende Element speichern. Die Ereignismethode lstAusgewaehlteKunden_PreviewMouseDown ändern wir wie folgt ab:

private void lstAusgewaehlteKunden_PreviewMouseDown(object sender, MouseButtonEventArgs e) {
     try {
         if (e.LeftButton == MouseButtonState.Pressed) {
             var item = (ListBoxItem)ItemsControl.ContainerFromElement(lst, (DependencyObject)e.OriginalSource);
             Kunde kunde = (Kunde)item.Content;
             DragDropData dragDropData = new DragDropData
             {
                 ActualData = kunde,
             };
             DragDrop.DoDragDrop(lst, dragDropData, DragDropEffects.Move);
         }
     }
     catch (System.Exception ex) {
         MessageBox.Show(ex.Message);
         throw;
     }

Dies war die Leseprobe dieses Artikels.
Melden Sie sich an, um auf den vollständigen Artikel zuzugreifen.

Bitte geben Sie die Zeichenfolge in das nachfolgende Textfeld ein

Die mit einem * markierten Felder sind Pflichtfelder.

Neues aus unseren Magazinen
Listenfeld: Reihenfolge mehrerer Einträge...

Wir haben bereits in mehreren Beiträgen beschrieben, wie Sie die individuelle Reihenfolge von Elementen einer Tabelle über den Inhalt eines Feldes etwa namens »ReihenfolgeID« einstellen können –... [mehr]

Diagramme mit gefilterten Daten

In Ausgabe 2/2019 haben wir in zwei Artikeln die modernen Diagramme von Access vorgestellt. Im vorliegenen Beitrag zeigen wir Ihnen, wie Sie diese abhängig von den in einem Formular angezeigten... [mehr]

Benutzerverwaltung mit verschlüsselten...

Wenn Sie in einer Access-Anwendung Benutzer verwalten wollen, die sich per Benutzername und Kennwort an die Anwendung anmelden, sollten Sie sehr sensibel mit den in der Anwendung gespeicherten... [mehr]

HTML-Tabellen mit fester Kopfzeile

In den vorherigen Ausgaben von Access im Unternehmen und in der aktuellen Ausgabe arbeiten wir in einigen Beiträgen mit dem Webbrowser-Steuerelement und stellen Daten, die wir mit den Bordmitteln... [mehr]

Flexible HTML-Tabellen mit fester Kopfzeile

Im Beitrag »HTML-Tabellen mit fester Kopfzeile« haben wir gezeigt, wie Sie Daten aus einer bestimmten Abfrage in einem Webbrowser-Steuerelement so anzeigen, dass die Spaltenköpfe oben fixiert... [mehr]

Berechtigungen per HTML verwalten

Im Beitrag »Benutzerverwaltung mit verschlüsselten Kennwörtern« stellen wir eine Lösung vor, in der wir die Berechtigungen von Benutzergruppen an Datenbankobjekten definieren. Dort benötigen wir... [mehr]

Benutzer und Berechtigungen ermitteln

In den Beiträgen »Benutzerverwaltung mit verschlüsselten Kennwörtern« und »Berechtigungen per HTML verwalten« haben wir die Voraussetzungen für eine Benutzerverwaltung geschaffen. Im vorliegenden... [mehr]

Zugriffsrechte mit Datenmakros

Es gibt verschiedene Möglichkeiten, auf Basis des aktuell angemeldeten Benutzers sicherzustellen, dass dieser nur die für ihn vorgesehenen Aktionen mit Daten durchführen darf – beispielsweise durch... [mehr]

Kennwörter generieren

Für den einen oder anderen Zweck möchten Sie vielleicht Kennwörter generieren oder in einer Benutzeroberfläche die Möglichkeit zum Generieren von Kennwörtern anbieten. Wenn Sie etwa Benutzer zu... [mehr]

Neuer Datensatz von Frontend zu Backend

Für manche Themen gibt es keine kurze, prägnante Überschrift. In diesem Fall wollen wir zeigen, wie Sie einen neuen Datensatz anlegen, der in einer temporären Tabelle im Frontend gespeichert wird,... [mehr]