Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Über den Autor
Vorwort zur 4. Auflage
1 Allgemeine Einführung in .NET
2 Grundlagen der Sprache C#
3 Klassendesign und Vererbung
4 Weitere .NET-Datentypen
5 Weitere Möglichkeiten von C#
6 Projektmanagement und Visual Studio 2008
7 Fehlerbehandlung und Debugging
8 LINQ
9 Multithreading und asynchrone Methodenaufrufe
10 Arbeiten mit Dateien und Streams
11 Serialisierung
12 Einige wichtige .NET-Klassen
13 Grundlagen zum Erstellen einer Windows-Anwendung
14 Die wichtigsten Steuerelemente
15 Tastatur- und Mausereignisse
16 MDI-Anwendungen
17 Grafische Programmierung mit GDI+
18 Das Drucken (Printing)
19 Steuerelemente entwickeln
20 Programmiertechniken
21 WPF – die Grundlagen
22 Die Layoutcontainer
23 Die WPF-Controls
24 Konzepte von WPF
25 ADO.NET – die Verbindung zu einer Datenbank herstellen
26 Die Datenbankabfrage
27 Der SqlDataAdapter
28 Daten im lokalen Speicher – das DataSet
29 Eine Datenbank aktualisieren
30 Stark typisierte DataSets
31 Weitergabe von Anwendungen
Stichwort

Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Visual C# 2008 von Andreas Kuehnel
Das umfassende Handbuch
Buch: Visual C# 2008

Visual C# 2008
geb., mit DVD
1.366 S., 49,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1172-7
Pfeil 20 Programmiertechniken
Pfeil 20.1 Drag
Pfeil 20.1.1 Der Ablauf einer Drag
Pfeil 20.1.2 Das Einleiten einer Drag
Pfeil 20.1.3 Die Ereignisse des Empfängers einer Drag
Pfeil 20.1.4 Programmbeispiele
Pfeil 20.2 API-Aufrufe mit PInvoke
Pfeil 20.2.1 Das Attribut »DllImportAttribute«
Pfeil 20.2.2 Datentypen von API-Funktionen
Pfeil 20.3 Entwickeln vom Windows-Dienstanwendungen
Pfeil 20.3.1 »Windows-Dienst«-Projekte in der Entwicklungsumgebung
Pfeil 20.3.2 Die Methoden eines Dienstes
Pfeil 20.3.3 Die Eigenschaften eines Dienstes
Pfeil 20.3.4 Die Installation eines Windows-Dienstes
Pfeil 20.3.5 Beispielprogramm »FileWatchService«
Pfeil 20.3.6 Dienste mittels Programmcode steuern
Pfeil 20.4 Die Zwischenablage
Pfeil 20.4.1 Speichern und Abrufen von Daten aus der Zwischenablage
Pfeil 20.4.2 Andere Methoden, um Daten in die Zwischenablage zu schreiben und abzurufen
Pfeil 20.4.3 Mehrere Datenformate in der Zwischenablage
Pfeil 20.4.4 Eigene Datenformate in die Zwischenablage schreiben
Pfeil 20.4.5 Beispielprogramm – das Menü »Bearbeiten«
Pfeil 20.5 Lokalisierung von Programmen
Pfeil 20.5.1 Lokalisierung von Komponenten
Pfeil 20.5.2 Zusätzliche Lokalisierungsdateien

20 Programmiertechniken


Galileo Computing - Zum Seitenanfang

20.1 Drag&Drop-Operationen Zur nächsten ÜberschriftZur vorigen Überschrift

Drag & Drop gehört zu den fundamentalsten Techniken der Windows-Betriebssysteme. Damit wird es einem Anwender ermöglicht, ein Objekt zu markieren und es bei gedrückter Maustaste an eine andere Stelle zu ziehen. Der Empfänger kann sich sowohl in derselben als auch in einer anderen Anwendung befinden. Unterstützend erhält der Anwender während des Ziehvorgangs ein visuelles Feedback, wenn sich der Mauszeiger über einer Komponente befindet, die in der Lage ist, das gezogene Objekt aufzunehmen. Diese Technik wird beispielsweise im Windows Explorer sehr gern dazu benutzt, eine oder mehrere Dateien in ein anderes Verzeichnis zu verschieben oder zu kopieren.

Bei Drag&Drop-Vorgängen spielen immer zwei Elemente eine Rolle: die Quelle, aus der ein Objekt gezogen wird, und der Empfänger, der das Objekt entgegennimmt. Beim Kopieren erhält der Empfänger eine Kopie des Objekts, beim Verschieben wird das Objekt in der Quelle gelöscht, und bei einer Verknüpfungsoperation verweisen sowohl die Quelle als auch das Ziel auf dasselbe Objekt.

In Abhängigkeit vom Status der Umschalttasten wird entschieden, ob eine Operation ein Objekt kopiert, verschiebt oder nur verknüpft. Wird keine Taste gedrückt, handelt es sich üblicherweise um eine Verschiebeoperation; ist die Strg -Taste während des Vorgangs gedrückt, wird kopiert, und die Kombination aus Shift und Strg -Taste bewirkt das Verknüpfen.


Galileo Computing - Zum Seitenanfang

20.1.1 Der Ablauf einer Drag&Drop-Operation Zur nächsten ÜberschriftZur vorigen Überschrift

Normalerweise werden Drag & Drop-Operationen als Reaktion auf das MouseDown-Ereignis ausgelöst. Meistens handelt es sich dabei um die linke Maustaste, in manchen Anwendungen sind aber auch Operationen über die rechte Maustaste möglich. Um eine Drag&Drop-Operation einzuleiten, wird im Ereignishandler die Methode DoDragDrop des Startelements aufgerufen.

Nicht jede Komponente ist automatisch ein potenzieller Empfänger der Drag&Drop-Operation. Vielmehr müssen die Komponenten, die als Empfänger in Frage kommen, die Eigenschaft AllowDrop=true eingestellt haben.

In Verbindung mit dem Ziehvorgang treten mehrere Ereignisse auf. Die beiden wichtigsten sind DragEnter und DragDrop. Da mit Drag & Drop die verschiedensten Datenformate bewegt werden können (Zeichenfolgen, Dateien, Images usw.), muss jeder potenzielle Empfänger einer Drag&Drop-Operation überprüfen, ob er das aktuell gezogene Datenformat überhaupt aufnehmen kann. Das passiert im Ereignis DragEnter. Das Ablegen des gezogenen Objekts erfolgt dann im Ereignis DragDrop.


Galileo Computing - Zum Seitenanfang

20.1.2 Das Einleiten einer Drag&Drop-Operation Zur nächsten ÜberschriftZur vorigen Überschrift

Um die Drag&Drop-Operation auszulösen, ist der Aufruf der Methode DoDragDrop notwendig, der im ersten Parameter das zu kopierende oder zu verschiebende Objekt übergeben wird. Der zweite Parameter vom Typ DragDropEffects beschreibt, welche Operationen mit dem Objekt möglich sind.

public DragDropEffects DoDragDrop(object, DragDropEffects);

Die Methode befindet sich so lange in der Ausführung, bis die Operation abgeschlossen ist. Der Rückgabewert der Methode beschreibt, wie der Empfänger die Daten entgegengenommen hat. In den meisten Fällen werden Sie aber den Rückgabewert vermutlich ignorieren können.

Die Mitglieder der Enumeration DragDropEffects können bitweise verknüpft werden, um mit einem Methodenaufruf mehrere verschiedene Operationen zu erlauben.


Tabelle 20.1 Die Enumeration »DragDropEffects«

Mitglied Beschreibung

None

Die Daten werden vom Ziel nicht akzeptiert.

Copy

Die Daten werden in das Ziel kopiert.

Move

Die Daten aus der Quelle werden in das Ziel verschoben.

Link

Die Daten aus der Quelle werden mit dem Ziel verknüpft.

Scroll

Der Bildlauf wird begonnen oder momentan im Ziel durchgeführt.

All

Die Daten werden kopiert, aus der Quelle entfernt und über einen Bildlauf im Ablageziel abgelegt.


So einfach im ersten Moment das Einleiten einer Drag&Drop-Operation erscheinen mag, so schwierig kann es sich bei der Programmierung erweisen. Der Grund dafür ist, dass einige Steuerelemente bei einem Click-Ereignis eine Standardreaktion zeigen. Die Problematik ist, zwischen dem Standardverhalten und der Drag&Drop-Operation zu unterscheiden.


Galileo Computing - Zum Seitenanfang

20.1.3 Die Ereignisse des Empfängers einer Drag&Drop-Operation Zur nächsten ÜberschriftZur vorigen Überschrift

Der Empfänger muss auch als ein solcher konfiguriert sein, standardmäßig ist das nämlich nicht der Fall. Ein Drag&Drop-Empfänger wird erst zu einem solchen, wenn die von der Klasse Control geerbte Eigenschaft AllowDrop auf true festgelegt ist und die Komponente damit ihre Empfangsbereitschaft signalisiert.

public virtual bool AllowDrop {get; set;}

Bei einer als Empfänger registrierten Komponente spielen insgesamt vier Ereignisse eine Rolle: DragEnter, DragOver, DragDrop und DragLeave:

public event DragEventHandler DragEnter; public event DragEventHandler DragOver; public event DragEventHandler DragDrop; public event EventHandler DragLeave;

Machen wir uns zunächst deutlich, unter welchen Umständen die Ereignisse ausgelöst werden.

  • Das Ereignis DragEnter wird ausgelöst, wenn der Mauszeiger in den Bereich eines Drag&Drop-Empfängers eindringt. Dabei kann es sich um eine Form oder um ein Steuerelement handeln. Das Ereignis wird dazu benutzt, um zu prüfen, ob das betreffende Steuerelement in der Lage ist, das Datenformat des gezogenen Objekts aufzunehmen. Ist das nicht der Fall, wird ein Symbol angezeigt, das an ein Verbotsschild erinnert. Dieses Symbol hat noch eine weiterreichende Konsequenz. Solange nämlich dieses Symbol angezeigt wird, tritt auch kein DragDrop-Ereignis auf, wenn der Anwender die Maustaste loslässt. Die Daten werden dann nicht fallen gelassen.
  • DragOver ist mit dem Ereignis MouseOver vergleichbar und tritt kontinuierlich auf, während die Maus über die Komponente bewegt wird. Dabei wird die Darstellung des Cursors abhängig davon geändert, ob es sich um einen Verschiebe- oder Kopiervorgang handelt. Im Windows Explorer beispielsweise wird der Cursor bei einer Verschiebeoperation durch einen Pfeil gekennzeichnet, beim Kopieren durch ein zusätzliches »+«-Zeichen am rechten unteren Ende des Pfeils. Über einem Element, das kein Empfänger einer Drag&Drop-Operation ist, wird sich der Mauszeiger nicht ändern und stattdessen einen Kreis mit dem schrägen roten Balken anzeigen.
  • Wird die gedrückte Maustaste über dem Empfänger losgelassen, kommt es zum DragDrop-Ereignis, und das Objekt wird abgelegt. Wie das losgelassene Objekt im Empfänger behandelt wird, hängt von den Anforderungen ab.
  • Wird mit gedrückter Maustaste der Bereich eines möglichen Empfängers verlassen, wird dessen Ereignis DragLeave ausgelöst. Nur in wenigen Fällen werden Sie einen Ereignishandler benötigen, um beim Verlassen des Empfängers eine Operation auszuführen.

Die Parameterliste der Ereignishandler

Das Ereignis DragLeave wird von einem EventArgs-Objekt begleitet, das uns schon oft begegnet ist und von dem wir wissen, dass es keine ereignisrelevanten Daten liefert. Daher können wir auf eine weitergehende Beschreibung verzichten.

Anders sieht es bei den drei Ereignissen DragEnter, DragDrop und DragOver aus. Die Ereignishandler dieser Ereignisse empfangen ein Objekt vom DragEventArgs, das eine Reihe von Eigenschaften bereitstellt, um genauere und verwertbare Informationen über die laufende Operation zu liefern.


Tabelle 20.2 Eigenschaften des »DragEventArgs«-Objekts

Eigenschaft Beschreibung

AllowEffected

Diese Eigenschaft ist schreibgeschützt und beschreibt die Optionen, die dem Empfänger von der Quelle zur Verfügung gestellt werden (Kopieren, Verschieben oder Verknüpfen). Damit enthält diese Eigenschaft die Kombination von DragDropEffects, die beim Aufruf der Methode DoDragDrop dem zweiten Parameter übergeben worden sind.

Data

Enthält die dem Ereignis zugeordneten Daten. Die Daten sind vom Typ IDataObject.

Effect

Diese Eigenschaft, die ebenfalls vom Typ DragDropEffects ist, legt die Optionen des Drag&Drop-Vorgangs und somit auch das Aussehen der Maus für den Empfänger fest. Effect muss insbesondere im Ereignishandler von DragEnter eingestellt werden, da ansonsten ein Mauscursor dargestellt wird, der symbolisiert, dass kein DragDrop-Ereignis ausgelöst wird. Eingestellt werden dürfen aber nur Werte, die auch unter AllowEffected angegeben sind.

KeyState

Ruft den aktuellen Zustand von (ª), (Strg), (Alt) sowie den Zustand der Maustasten ab (siehe auch Tabelle 20.3).

X, Y

Ruft die x- bzw. y-Koordinate des Mauszeigers in Bildschirmkoordinaten ab.



Hinweis Die Daten, die Sie während einer Drag&Drop-Operation ziehen, liegen im Format IDataObject vor. Diesen Typ mit seinen Methoden wie beispielsweise GetDataPresent und GetFormats werden wir im Zusammenhang mit der Programmierung der Zwischenablage weiter unten besprechen.


Beachten Sie bitte, dass X und Y die Koordinaten des Mauszeigers auf dem Bildschirm liefern. Diese Werte sind normalerweise wertlos, können aber relativ einfach in die Koordinaten eines Steuerelements umgerechnet werden. Dabei hilft die PointToClient-Methode weiter, die auf dem erforderlichen Steuerelement aufgerufen wird:

Point pt = Steuerelement.PointToClient(this.MousePosition);

Die Eigenschaft KeyState ist folgendermaßen definiert:

public int KeyState {get;}

Diese Eigenschaft verwendet erstaunlicherweise nicht wie ansonsten üblich eine Enumeration, sondern beschreibt den Zustand aller in Frage kommenden Tasten über einen Integer. Da KeyState mit dem Flags-Attribut verknüpft ist, wird der Rückgabewert der Eigenschaft bitweise interpretiert.


Tabelle 20.3 Die Bitflags der Eigenschaft »KeyState«

Bitflag Taste

1

linke Maustaste

2

rechte Maustaste

4

(ª)-Taste

8

(Strg)-Taste

16

mittlere Maustaste

32

(Alt)-Taste


Das »QueryContinueDrag«-Ereignis der Ereignisquelle

Für das Steuerelement, das für die Drag&Drop-Operation als Quelle verantwortlich ist, werden permanent die QueryContinueDrag-Ereignisse ausgelöst. Das Ereignis bietet sich insbesondere an, um einen eingeleiteten Vorgang vorzeitig abzubrechen und dabei festzulegen, was mit dem gezogenen Objekt passieren soll.

Das Ereignis schickt ein Objekt vom Typ QueryContinueDragEventArgs an seinen Ereignishandler. Dieses Objekt hat drei Eigenschaften:

  • Action
  • EscapePressed
  • KeyState

KeyState teilt mit, welche Tasten während der Operation gedrückt sind (siehe Tabelle 20.3), und EscapePressed ruft ab, ob der Anwender die ESC -Taste gedrückt hat.

Mit Action lässt sich der Status der andauernden Operation bestimmen und beeinflussen. Diese Eigenschaft ist vom Typ der Enumeration DragAction, mit der der Fortgang der Operation festgelegt werden kann.


Tabelle 20.4 Die Enumeration »DragAction«

Member Beschreibung

Cancel

Die Operation wird abgebrochen. Dabei werden die Daten nicht abgelegt.

Continue

Die Operation wird fortgesetzt.

Drop

Die Operation wird beendet. Dabei werden die Daten abgelegt.



Galileo Computing - Zum Seitenanfang

20.1.4 Programmbeispiele topZur vorigen Überschrift

An den folgenden vier Beispielen wollen wir uns nun ansehen, wie Drag & Drop realisiert werden kann. Im ersten Beispiel wird nur eine einfache Operation zwischen zwei Textboxen gezeigt, im zweiten eine Operation, bei der zwischen zwei Pictureboxen ein Bildchen hin- und hergeschoben bzw. kopiert wird. Drag & Drop zwischen zwei Listboxen ist nur unter erheblichem Programmieraufwand möglich, wenn die Listboxen eine Mehrfachauswahl zulassen. Das dritte Beispiel stellt dazu eine gleichwertige Alternative vor, die anstelle von Listboxen ListView-Steuerelemente benutzt. Im letzten Beispiel wird Ihnen abschließend noch gezeigt, wie Dateien bei einer Drag&Drop-Operation behandelt werden.

Drag & Drop zwischen zwei Textboxen

Die Form des folgenden Beispiels enthält die beiden Textboxen textBox1 und textBox2. Der Inhalt von textBox1 soll mittels Drag & Drop in die textBox2 verschoben oder kopiert werden. Zum Kopieren muss während des Ziehvorgangs die Strg -Taste gedrückt sein. Die Eigenschaft AllowDrop von textBox2 ist auf true eingestellt.

// -------------------------------------------------------------
// Beispiel: ...\Kapitel 20\DragAndDrop_Textboxen
// -----------------------------------------------------------------
private void textBox1_MouseDown(object sender, MouseEventArgs e) { 
  textBox1.DoDragDrop(textBox1.Text, 
             DragDropEffects.Copy | DragDropEffects.Move);

}

private void textBox2_DragEnter(object sender, DragEventArgs e) { 
  if(e.Data.GetDataPresent(DataFormats.Text)) 
    // wenn die Strg-Taste gedrückt ist 
    if((e.KeyState & 8) == 8) 
      e.Effect = DragDropEffects.Copy; 
      // wenn nur die linke Maustaste gedrückt ist 
    else 
      e.Effect = DragDropEffects.Move; 
  else 
    e.Effect = DragDropEffects.None; 
}

private void textBox2_DragDrop(object sender, DragEventArgs e) { 
  textBox2.Text = e.Data.GetData(DataFormats.Text).ToString(); 
  if((e.KeyState & 8) != 8) 
    textBox1.Clear(); 
}

Eingeleitet wird die Drag&Drop-Operation mit dem Drücken der linken Maustaste im Textfeld textBox1. Dabei wird die Methode DoDragDrop aufgerufen, der im ersten Argument die zu erfassenden Daten mitgeteilt werden. Hier ist es der gesamte Inhalt von textBox1. Im zweiten Argument ist festgelegt, dass die Daten sowohl verschoben als auch kopiert werden können.

textBox1.DoDragDrop(textBox1.Text, 
              DragDropEffects.Copy | DragDropEffects.Move);

Dringt der Mauszeiger bei gleichzeitig gedrückter linker Maustaste in den Bereich des Objekts textBox2 ein, wird das Ereignis DragEnter ausgelöst. Wir benutzen den Ereignishandler dazu, um zunächst einmal festzustellen, ob die von der aktuellen Drag&Drop-Operation erfassten Daten auch im Textformat vorliegen. Theoretisch wäre es auch möglich, dass aus einer anderen Quelle heraus Daten verschoben werden, die nicht im Text-, sondern zum Beispiel im Bildformat vorliegen. Dann darf die Textbox natürlich auch nicht mit einem Symbol ihre Bereitschaft signalisieren, die Daten aufzunehmen.

Verläuft die Überprüfung in DragEnter mit

if(e.Data.GetDataPresent(DataFormats.Text))

positiv, gilt es festzustellen, ob die Strg -Taste gedrückt ist oder nicht. Ist diese Zustandstaste gedrückt, werden die Daten – falls sie in der Textbox textBox2 fallen gelassen werden – kopiert, andernfalls nur verschoben. Das dazugehörige Symbol wird durch die Übergabe einer DragDropEffects-Konstante an die Eigenschaft Effects festgelegt, beispielsweise so:

if((e.KeyState & 8) == 8) 
  e.Effect = DragDropEffects.Copy;

Die Zuweisung an Effect hat noch einen weiteren, sehr wichtigen Hintergrund, der zu erkennen ist, wenn man den Code in DragEnter auskommentiert: Es ist dann keine Drop-Operation mehr möglich. Als Symbol wird in diesem Fall nur noch ein Kreis mit einem schrägen Balken angezeigt. In DragEnter wird also folglich die Bereitschaft der Komponte festgelegt, die Daten zu empfangen, und darüber hinaus auch, wie die Daten behandelt werden.


Wird die Maustaste losgelassen, während sich der Mauszeiger über textBox2 befindet, kommt es zum Ereignis DragDrop. Hier werden die Daten nach vorhergehender Konvertierung in den Typ string in das Objekt textBox2 geschrieben. Außerdem muss überprüft werden, ob es sich um eine Verschiebe- oder Kopieroperation handelt. Im ersteren Fall müssen die verschobenen Daten in der Quelle gelöscht werden.

Da Drag & Drop auch anwendungsübergreifend funktioniert, können Sie aus einem beliebigen textbasierten Dokument heraus Daten verschieben. Andererseits wird das Verschieben beispielsweise einer Bitmap-Datei von der Textbox im Beispielprogramm ignoriert.

Drag & Drop zwischen zwei Pictureboxen

Genauso einfach wie das Verschieben einer Zeichenfolge ist das Verschieben eines Bildes. Der Code unterscheidet sich nur geringfügig, da nur der abweichende Datentyp zu beachten ist.

Im folgenden Beispiel enthält die Form zwei Pictureboxen. Nach dem Start enthält die mit pic1 bezeichnete Picturebox ein Bild, das in die mit pic2 bezeichnete Picturebox entweder verschoben oder kopiert werden kann. Weil es nur geringfügig mehr Codierungsaufwand bedeutet, ist in diesem Beispiel die Drag&Drop-Operation in beide Richtungen möglich. Dazu werden die Ereignisse MouseDown, DragEnter und DragDrop mit dem gleichen Ereignishandler verknüpft. Im DragDrop-Ereignishandler muss in dem Fall, dass eine Verschiebeoperation vorliegt, das Bild in der richtigen Quelle gelöscht werden. Dazu ist die Referenz des sender-Parameters zu überprüfen.


Hinweis Die Eigenschaft AllowDrop der Pictureboxen muss natürlich auf true gesetzt werden. Im Eigenschaftsfenster wird diese Eigenschaft aber aus unerklärlichen Gründen nicht aufgelistet. Sie müssen also eine entsprechende Anweisung codieren. Dabei werden Sie feststellen, dass AllowDrop auch nicht in der IntelliSense-Liste zu finden ist. Setzen Sie sich darüber einfach hinweg.


// -------------------------------------------------------------
// Beispiel: ...\Kapitel 20\DragAndDrop_Bilddateien
// -----------------------------------------------------------------
private void Form1_Load(object sender, EventArgs e) { 
  pic1.AllowDrop = true; 
  pic2.AllowDrop = true; 
}

private void InitializeComponent() { 
  pic1.DragEnter += new DragEventHandler(pic_DragEnter); 
  pic1.DragDrop += new DragEventHandler(pic_DragDrop); 
  pic1.MouseDown += new MouseEventHandler(pic_MouseDown); 
  pic2.DragEnter += new DragEventHandler(pic_DragEnter); 
  pic2.DragDrop += new DragEventHandler(pic_DragDrop); 
  pic2.MouseDown += new MouseEventHandler(pic_MouseDown); 
}

private void pic_MouseDown(object sender, MouseEventArgs e) { 
  PictureBox pic = (PictureBox)sender; 
  // wenn ein Bild angezeigt wird, die Drag&Drop-Operation 
  // einleiten 
  if(pic.Image != null) 
    pic.DoDragDrop(pic.Image, 
               DragDropEffects.Copy | DragDropEffects.Move); 
}

private void pic_DragEnter(object sender, DragEventArgs e) { 
  if(e.Data.GetDataPresent(DataFormats.Bitmap)) 
    // wenn die Strg-Taste gedrückt ist 
    if((e.KeyState & 8) == 8) 
      e.Effect = DragDropEffects.Copy; 
    // wenn nur die linke Maustaste gedrückt ist 
    else 
      e.Effect = DragDropEffects.Move; 
  else 
    e.Effect = DragDropEffects.None; 
}

private void pic_DragDrop(object sender, DragEventArgs e) { 
  PictureBox pic = (PictureBox)sender; 
  // die empfangenen Daten in den Typ Image konvertieren 
  pic.Image = (Image)e.Data.GetData(DataFormats.Bitmap); 
  if((e.KeyState & 8) != 8) 
    if(pic == pic1) 
      pic2.Image = null; 
    else 
      pic1.Image = null; 
}

Drag & Drop zwischen Listen

Wenn Sie die Elemente zwischen zwei Listen mit Drag & Drop verschieben oder kopieren wollen, wird es etwas schwieriger. Normalerweise werden Sie sich bei einer Liste für den Typ ListBox entscheiden, der jedoch Probleme bereitet, wenn mehrere Listenelemente an der Operation teilnehmen sollen. In solchen Fällen ist der Typ ListView empfehlenswerter.

Das Steuerelement ListView hat, ebenso wie auch TreeView, ein zusätzliches Ereignis, mit dem das Ziehen eines oder mehrerer Elemente erleichtert wird: ItemDrag. Dieses Ereignis tritt auf, wenn zur Laufzeit mit dem Ziehen begonnen wird. Über die Eigenschaften des Args-Parameters kann man die bei dem Vorgang gedrückte Maustaste sowie das zu ziehende Element ermitteln, aber meistens wird der Ereignishandler nur dazu benutzt, die Methode DoDragDrop aufzurufen.

Im folgenden Beispielprogramm können die Listenelemente von zwei ListView-Objekten beliebig verschoben werden. Die Form enthält zwei dieser Steuerelemente, deren AllowDrop-Eigenschaft selbstverständlich wieder auf true gesetzt ist. Da standardmäßig nur eine einfache Auswahl möglich ist, sollte die Mehrfachauswahl mit der Eigenschaft MultiSelect eingestellt werden. Um die Listbox zu simulieren, ist View=List gewählt, aber es kann natürlich auch aus den anderen angebotenen Ansichten heraus verschoben werden.

Sehen wir uns zuerst den Code des ItemDrag-Ereignishandlers an, der mit beiden Listenansichten verknüpft ist:

private void ListView_ItemDrag(object sender, ItemDragEventArgs e) { 
  ListView listview = (ListView)sender; 
  ListViewItem[] items = new ListViewItem[listview.SelectedItems.Count]; 
  for(int i = 0; i < listview.SelectedItems.Count; i++) 
    items[i] = listview.SelectedItems[i]; 
  listview.DoDragDrop(new DataObject("ListViewItemData", items), 
  DragDropEffects.Move); 
}

Zuerst wird ein Array vom Typ ListViewItem deklariert, das anschließend mit den ausgewählten Listenelementen aus der SelectedListViewItemCollection der Listenansicht gefüllt wird. Beim Aufruf der DoDragDrop-Methode müssen zuerst die an der Operation beteiligten Daten bekannt gegeben werden. Damit auch wirklich nur die dafür vorgesehene Listenansicht die Daten empfangen kann, spezifizieren wir ein eigenes DataObject. Dazu übergeben wir dem Konstruktor zuerst einen beliebigen Bezeichner für die zu verschiebenden Daten und anschließend die Daten selbst. Als Operation ist in diesem Beispiel nur das Verschieben vorgesehen.

Im Drag&Drop-Empfänger wird zuerst das Ereignis DragEnter ausgelöst. In diesem werden die gezogenen Daten einer Typuntersuchung unterzogen. Hier fragen wir nach dem Bezeichner, den wir DataObject-Konstruktor genannt haben. Sind die Daten vom Typ ListViewItemData, kann der Verschiebevorgang initialisiert werden.

private void listView_DragEnter(object sender, DragEventArgs e) { 
  if(e.Data.GetDataPresent("ListViewItemData")) 
    e.Effect = DragDropEffects.Move; 
  else 
    e.Effect = DragDropEffects.None; 
}

Dem Fallenlassen der gezogenen Daten und dem damit ausgelösten Ereignis DragDrop kommt jetzt nur noch die Aufgabe zu, den Empfänger mit den gezogenen Listenelementen zu füllen und diese gleichzeitig in der Quelle zu löschen.

private void listView_DragDrop(object sender, DragEventArgs e) { 
  ListView listview = (ListView)sender; 
  ListViewItem[] items = (ListViewItem[])(e.Data.GetData("ListViewItemData")); 
  for(int i = 0; i < items.Length; i++) { 
    listview.Items.Add(items[i].Text); 
  if(listview == listView1) 
    listView2.Items.Remove(listView2.SelectedItems[0]); 
  else 
    listView1.Items.Remove(listView1.SelectedItems[0]); 
}

Den vollständigen Code zu diesem Beispiel finden Sie auf der Buch-DVD unter \Kapitel 20\DragAndDrop_Listen.

Drag & Drop von Dateien

Das letzte Beispielprogramm soll Ihnen demonstrieren, wie Dateien gezogen werden – hier im Besonderen Dateien mit Textinhalt, aber grundsätzlich können Sie auf diese Weise mit jedem Dateityp verfahren. Die Dateien können beispielsweise aus dem Windows Explorer in die Textbox der Form gezogen werden. Der Dateiinhalt wird dabei in der Textbox angezeigt.

Das Datenformat von Dateien, die an einer Drag&Drop-Operation teilnehmen, wird durch das Feld FileDrop der Klasse DataFormat beschrieben. Der Rückgabewert der Methode GetData ist dann die Zeichenfolge, die den Zugriffspfad auf die gezogene Datei beschreibt. Da es im Windows Explorer auch möglich ist, mehrere Dateien zu ziehen, könnte es sich auch um ein Array handeln, das in ein Zeichenfolge-Array konvertiert werden muss.

Das Array wird in einer Schleife Element für Element durchlaufen. Nach einer Überprüfung der Dateierweiterung (es sind nur Dateien mit den Endungen TXT, INI und LOG zugelassen) wird die sich jeweils im Zugriff befindliche Datei geöffnet und im Fenster angezeigt.

// -------------------------------------------------------------
// Beispiel: ...\Kapitel 20\DragAndDrop_Dateien
// -----------------------------------------------------------------
private void textBox1_DragDrop(object sender, DragEventArgs e) { 
  if(e.Data.GetDataPresent(DataFormats.FileDrop)) { 
    // liefert in einem Array alle im Explorer ausgewählten Dateien 
    string[] strFileName = (string[])e.Data.GetData(DataFormats.FileDrop); 
    StreamReader sr; 
    // alle ausgewählten Dateien in der Textbox anzeigen 
    for(int i = 0; i < strFileName.Length; i++) { 
      try { 
        // nur TXT-, LOG- und INI-Dateien einlesen 
        if(Path.GetExtension(strFileName[i]) == ".txt" || 
          Path.GetExtension(strFileName[i]) == ".log" || 
          Path.GetExtension(strFileName[i]) == ".ini") 
          sr = new StreamReader(strFileName[i]); 
        else 
          continue; 
      } 
      catch (IOException ex) { 
        MessageBox.Show(ex.Message); 
        return; 
      } 
      textBox1.Text += new string('=', 60) + "\r\n"; 
      textBox1.Text += "Datei: " + strFileName[i] + "\r\n"; 
      textBox1.Text += new string('=', 60) + "\r\n"; 
      textBox1.Text += sr.ReadToEnd() + "\r\n"; 
      sr.Close(); 
    } 
  } 
}

private void textBox1_DragEnter(object sender, DragEventArgs e) { 
  if (e.Data.GetDataPresent(DataFormats.FileDrop)) 
    e.Effect = DragDropEffects.Link; 
  else 
    e.Effect = DragDropEffects.None; 
}


Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen. >> Zum Feedback-Formular
<< zurück
  Zum Katalog
Zum Katalog: Visual C# 2008
Visual C# 2008
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Visual C# 2012






 Visual C# 2012


Zum Katalog: Professionell entwickeln mit Visual C# 2012






 Professionell
 entwickeln mit
 Visual C# 2012


Zum Katalog: Windows Presentation Foundation






 Windows Presentation
 Foundation


Zum Katalog: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Katalog: C++ Handbuch






 C++ Handbuch


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2008
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Rheinwerk Computing]

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de