Freigeben über


Anleitung: Aktivieren von Drag-and-Drop bei einem Benutzersteuerelement

In dieser exemplarischen Vorgehensweise wird veranschaulicht, wie Sie ein benutzerdefiniertes Benutzersteuerelement erstellen, das an der Übertragung von Drag-and-Drop-Daten in Windows Presentation Foundation (WPF) teilnehmen kann.

In dieser exemplarischen Vorgehensweise erstellen Sie einen benutzerdefinierten WPF UserControl , der eine Kreisform darstellt. Sie implementieren Funktionen für das Steuerelement, um die Datenübertragung durch Ziehen und Ablegen zu ermöglichen. Wenn Sie z. B. von einem Kreis-Steuerelement auf ein anderes ziehen, werden die Füllfarbesdaten aus dem Quellkreis in das Ziel kopiert. Wenn Sie von einer Kreissteuerung zu einem TextBox ziehen, wird die Darstellung der Füllfarbe als Zeichenfolge in die TextBox kopiert. Außerdem erstellen Sie eine kleine Anwendung, die zwei Steuerungselemente für das Panel enthält und eine TextBox, um die Drag-and-Drop-Funktionalität zu testen. Sie schreiben Code, mit dem die Panels abgelegte Kreisdaten verarbeiten können, wodurch Sie Kreise aus der Children-Auflistung eines Panels in das andere verschieben oder kopieren können.

In dieser exemplarischen Vorgehensweise werden folgende Aufgaben erläutert:

  • Erstellen Sie ein benutzerdefiniertes Benutzersteuerelement.

  • Aktivieren Sie das Benutzersteuerelement als Ziehquelle.

  • Aktivieren Sie das Benutzersteuerelement als Drop-Ziel.

  • Aktivieren Sie ein Panel, um vom Benutzersteuerelement übertragene Daten zu empfangen.

Voraussetzungen

Sie benötigen Visual Studio, um diese Anleitung abzuschließen.

Erstellen des Anwendungsprojekts

In diesem Abschnitt erstellen Sie die Anwendungsinfrastruktur, die eine Hauptseite mit zwei Paneelen und einem TextBox umfasst.

  1. Erstellen Sie ein neues WPF-Anwendungsprojekt in Visual Basic oder Visual C# mit dem Namen DragDropExample. Weitere Informationen finden Sie unter Exemplarische Vorgehensweise: Meine erste WPF-Desktopanwendung.

  2. Öffnen Sie "MainWindow.xaml".

  3. Fügen Sie das folgende Markup zwischen den öffnenden und schließenden Grid Tags hinzu.

    Dieses Markup erstellt die Benutzeroberfläche für die Testanwendung.

    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <StackPanel Grid.Column="0"
                Background="Beige">
        <TextBox Width="Auto" Margin="2"
                 Text="green"/>
    </StackPanel>
    <StackPanel Grid.Column="1"
                Background="Bisque">
    </StackPanel>
    

Hinzufügen eines neuen Benutzersteuerelements zum Projekt

In diesem Abschnitt fügen Sie dem Projekt ein neues Benutzersteuerelement hinzu.

  1. Wählen Sie im Menü "Projekt" die Option "Benutzersteuerelement hinzufügen" aus.

  2. Ändern Sie im Dialogfeld " Neues Element hinzufügen " den Namen in Circle.xaml, und klicken Sie auf "Hinzufügen".

    Circle.xaml und sein CodeBehind werden dem Projekt hinzugefügt.

  3. Öffnen Sie Circle.xaml.

    Diese Datei enthält die Benutzeroberflächenelemente des Benutzersteuerelements.

  4. Fügen Sie dem Stamm Grid das folgende Markup hinzu, um ein einfaches Benutzersteuerelement mit einem blauen Kreis als Benutzeroberfläche zu erstellen.

    <Ellipse x:Name="circleUI" 
             Height="100" Width="100"
             Fill="Blue" />
    
  5. Öffnen Sie Circle.xaml.cs oder Circle.xaml.vb.

  6. Fügen Sie in C# den folgenden Code nach dem parameterlosen Konstruktor hinzu, um einen Kopierkonstruktor zu erstellen. Fügen Sie in Visual Basic den folgenden Code hinzu, um sowohl einen parameterlosen Konstruktor als auch einen Kopierkonstruktor zu erstellen.

    Damit das Benutzersteuerelement kopiert werden kann, fügen Sie der CodeBehind-Datei eine Kopierkonstruktormethode hinzu. Im vereinfachten Kreis-Benutzersteuerelement kopieren Sie nur die Füllung und die Größe des Benutzersteuerelements.

    public Circle(Circle c)
    {
        InitializeComponent();
        this.circleUI.Height = c.circleUI.Height;
        this.circleUI.Width = c.circleUI.Height;
        this.circleUI.Fill = c.circleUI.Fill;
    }
    
    Public Sub New()
        ' This call is required by the designer.
        InitializeComponent()
    End Sub
    
    Public Sub New(ByVal c As Circle)
        InitializeComponent()
        Me.circleUI.Height = c.circleUI.Height
        Me.circleUI.Width = c.circleUI.Height
        Me.circleUI.Fill = c.circleUI.Fill
    End Sub
    

Hinzufügen des Benutzersteuerelements zum Hauptfenster

  1. Öffnen Sie "MainWindow.xaml".

  2. Fügen Sie dem öffnenden Window Tag den folgenden XAML-Code hinzu, um einen XML-Namespaceverweis auf die aktuelle Anwendung zu erstellen.

    xmlns:local="clr-namespace:DragDropExample"
    
  3. Fügen Sie im ersten StackPanelCode den folgenden XAML-Code hinzu, um zwei Instanzen des Circle-Benutzersteuerelements im ersten Bereich zu erstellen.

    <local:Circle Margin="2" />
    <local:Circle Margin="2" />
    

    Der vollständige XAML-Code für das Panel sieht wie folgt aus.

    <StackPanel Grid.Column="0"
                Background="Beige">
        <TextBox Width="Auto" Margin="2"
                 Text="green"/>
        <local:Circle Margin="2" />
        <local:Circle Margin="2" />
    </StackPanel>
    <StackPanel Grid.Column="1"
                Background="Bisque">
    </StackPanel>
    

Implementieren von Drag Source-Ereignissen im Benutzersteuerelement

In diesem Abschnitt überschreiben Sie die OnMouseMove Methode und initiieren den Drag-and-Drop-Vorgang.

Wenn ein Ziehen gestartet wird (eine Maustaste gedrückt wird und die Maus verschoben wird), packen Sie die zu übertragenden Daten in ein DataObject. In diesem Fall enthält das Kreis-Steuerelement drei Datenelemente; eine Zeichenfolgendarstellung der Füllfarbe, eine doppelte Darstellung der Höhe und eine Kopie von sich selbst.

So initiieren Sie einen Drag-and-Drop-Vorgang

  1. Öffnen Sie Circle.xaml.cs oder Circle.xaml.vb.

  2. Fügen Sie die folgende OnMouseMove Außerkraftsetzung hinzu, um die Klassenbehandlung für das MouseMove Ereignis bereitzustellen.

    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);
        if (e.LeftButton == MouseButtonState.Pressed)
        {
            // Package the data.
            DataObject data = new DataObject();
            data.SetData(DataFormats.StringFormat, circleUI.Fill.ToString());
            data.SetData("Double", circleUI.Height);
            data.SetData("Object", this);
    
            // Initiate the drag-and-drop operation.
            DragDrop.DoDragDrop(this, data, DragDropEffects.Copy | DragDropEffects.Move);
        }
    }
    
    Protected Overrides Sub OnMouseMove(ByVal e As System.Windows.Input.MouseEventArgs)
        MyBase.OnMouseMove(e)
        If e.LeftButton = MouseButtonState.Pressed Then
            ' Package the data.
            Dim data As New DataObject
            data.SetData(DataFormats.StringFormat, circleUI.Fill.ToString())
            data.SetData("Double", circleUI.Height)
            data.SetData("Object", Me)
    
            ' Inititate the drag-and-drop operation.
            DragDrop.DoDragDrop(Me, data, DragDropEffects.Copy Or DragDropEffects.Move)
        End If
    End Sub
    

    Diese OnMouseMove Überschreibung führt die folgenden Aufgaben aus.

    • Überprüft, ob die linke Maustaste gedrückt wird, während die Maus bewegt wird.

    • Packt die Kreisdaten in ein DataObject. In diesem Fall verpackt das Circle-Steuerelement drei Datenelemente; eine Zeichenfolgendarstellung der Füllfarbe, eine doppelte Darstellung der Höhe und eine Kopie von sich selbst.

    • Ruft die statische DragDrop.DoDragDrop Methode auf, um den Drag-and-Drop-Vorgang zu initiieren. Sie übergeben die folgenden drei Parameter an die DoDragDrop Methode:

      • dragSource – Ein Verweis auf dieses Steuerelement.

      • data – Die DataObject im vorherigen Code erstellte Datei.

      • allowedEffects – Die zulässigen Drag-and-Drop-Vorgänge, die Copy oder Move sind.

  3. Drücken Sie F5-, um die Anwendung zu erstellen und auszuführen.

  4. Klicken Sie auf eines der Kreis-Steuerelemente und ziehen Sie es über das Panel, den anderen Kreis und den TextBox. Beim Ziehen über den TextBoxändert sich der Cursor, um auf eine Verschiebung hinzuweisen.

  5. Drücken Sie beim Ziehen eines Kreises über TextBox die STRG-TASTE. Beachten Sie, wie sich der Cursor ändert, der auf eine Kopie hinweist.

  6. Ziehen Sie einen Kreis auf das TextBox und lassen Sie ihn los. Die Darstellung der Füllfarbe des Kreises wird an den TextBox-String angefügt.

    Zeichenfolgendarstellung der Füllfarbe des Kreises DragDrop_ColorString

Standardmäßig ändert sich der Cursor während eines Drag-and-Drop-Vorgangs, um anzugeben, welche Auswirkungen das Ablegen der Daten hat. Sie können das Feedback anpassen, das dem Benutzer gegeben wird, indem Sie das GiveFeedback Ereignis behandeln und einen anderen Cursor festlegen.

Dem Benutzer Feedback geben

  1. Öffnen Sie Circle.xaml.cs oder Circle.xaml.vb.

  2. Fügen Sie die folgende OnGiveFeedback Außerkraftsetzung hinzu, um die Klassenbehandlung für das GiveFeedback Ereignis bereitzustellen.

    protected override void OnGiveFeedback(GiveFeedbackEventArgs e)
    {
        base.OnGiveFeedback(e);
        // These Effects values are set in the drop target's
        // DragOver event handler.
        if (e.Effects.HasFlag(DragDropEffects.Copy))
        {
            Mouse.SetCursor(Cursors.Cross);
        }
        else if (e.Effects.HasFlag(DragDropEffects.Move))
        {
            Mouse.SetCursor(Cursors.Pen);
        }
        else
        {
            Mouse.SetCursor(Cursors.No);
        }
        e.Handled = true;
    }
    
    Protected Overrides Sub OnGiveFeedback(ByVal e As System.Windows.GiveFeedbackEventArgs)
        MyBase.OnGiveFeedback(e)
        ' These Effects values are set in the drop target's
        ' DragOver event handler.
        If e.Effects.HasFlag(DragDropEffects.Copy) Then
            Mouse.SetCursor(Cursors.Cross)
        ElseIf e.Effects.HasFlag(DragDropEffects.Move) Then
            Mouse.SetCursor(Cursors.Pen)
        Else
            Mouse.SetCursor(Cursors.No)
        End If
        e.Handled = True
    End Sub
    

    Diese OnGiveFeedback Überschreibung führt die folgenden Aufgaben aus.

    • Überprüft die Effects Werte, die im Ereignishandler des Dropziels DragOver festgelegt sind.

    • Legt einen benutzerdefinierten Cursor basierend auf dem Effects Wert fest. Der Cursor soll dem Benutzer visuelles Feedback darüber geben, welche Auswirkungen das Ablegen der Daten haben wird.

  3. Drücken Sie F5-, um die Anwendung zu erstellen und auszuführen.

  4. Ziehen Sie eines der Circle-Steuerelemente über die Panels, den anderen Kreis und die TextBox. Beachten Sie, dass die Cursor jetzt die benutzerdefinierten Cursor sind, die Sie in der OnGiveFeedback Überschreibung angegeben haben.

    Ziehen und Ablegen mit benutzerdefinierten Cursorn

  5. Wählen Sie den Text green aus dem TextBox.

  6. Ziehen Sie den green Text auf eine Kreissteuerung. Beachten Sie, dass die Standardcursor angezeigt werden, um die Auswirkungen des Drag-and-Drop-Vorgangs anzugeben. Der Feedbackcursor wird immer von der Ziehquelle festgelegt.

Ereignisse für Drag-and-Drop-Ziele im Benutzersteuerelement implementieren

In diesem Abschnitt geben Sie an, dass das Benutzersteuerelement ein Drop-Ziel ist, überschreiben die Methoden, mit denen das Benutzersteuerelement ein Dropziel sein kann, und verarbeiten die darin abgelegten Daten.

So aktivieren Sie das Benutzersteuerelement als Dropziel

  1. Öffnen Sie Circle.xaml.

  2. Fügen Sie im öffnenden UserControl Tag die AllowDrop Eigenschaft hinzu, und legen Sie sie auf true.

    <UserControl x:Class="DragDropWalkthrough.Circle"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300"
                 AllowDrop="True">
    

Die OnDrop Methode wird aufgerufen, wenn die AllowDrop-Eigenschaft auf true gesetzt ist und Daten aus der Ziehquelle auf das Circle-Benutzersteuerungselement abgelegt werden. In dieser Methode verarbeiten Sie die fallen gelassenen Daten und wenden die Daten auf den Kreis an.

So verarbeiten Sie die verworfenen Daten

  1. Öffnen Sie Circle.xaml.cs oder Circle.xaml.vb.

  2. Fügen Sie die folgende OnDrop Außerkraftsetzung hinzu, um die Klassenbehandlung für das Drop Ereignis bereitzustellen.

    protected override void OnDrop(DragEventArgs e)
    {
        base.OnDrop(e);
    
        // If the DataObject contains string data, extract it.
        if (e.Data.GetDataPresent(DataFormats.StringFormat))
        {
            string dataString = (string)e.Data.GetData(DataFormats.StringFormat);
    
            // If the string can be converted into a Brush,
            // convert it and apply it to the ellipse.
            BrushConverter converter = new BrushConverter();
            if (converter.IsValid(dataString))
            {
                Brush newFill = (Brush)converter.ConvertFromString(dataString);
                circleUI.Fill = newFill;
    
                // Set Effects to notify the drag source what effect
                // the drag-and-drop operation had.
                // (Copy if CTRL is pressed; otherwise, move.)
                if (e.KeyStates.HasFlag(DragDropKeyStates.ControlKey))
                {
                    e.Effects = DragDropEffects.Copy;
                }
                else
                {
                    e.Effects = DragDropEffects.Move;
                }
            }
        }
        e.Handled = true;
    }
    
    Protected Overrides Sub OnDrop(ByVal e As System.Windows.DragEventArgs)
        MyBase.OnDrop(e)
        ' If the DataObject contains string data, extract it.
        If e.Data.GetDataPresent(DataFormats.StringFormat) Then
            Dim dataString As String = e.Data.GetData(DataFormats.StringFormat)
    
            ' If the string can be converted into a Brush, 
            ' convert it and apply it to the ellipse.
            Dim converter As New BrushConverter
            If converter.IsValid(dataString) Then
                Dim newFill As Brush = converter.ConvertFromString(dataString)
                circleUI.Fill = newFill
    
                ' Set Effects to notify the drag source what effect
                ' the drag-and-drop operation had.
                ' (Copy if CTRL is pressed; otherwise, move.)
                If e.KeyStates.HasFlag(DragDropKeyStates.ControlKey) Then
                    e.Effects = DragDropEffects.Copy
                Else
                    e.Effects = DragDropEffects.Move
                End If
            End If
        End If
        e.Handled = True
    End Sub
    

    Diese OnDrop Überschreibung führt die folgenden Aufgaben aus.

    • Verwendet die GetDataPresent Methode, um zu überprüfen, ob die gezogenen Daten ein Zeichenfolgenobjekt enthalten.

    • Verwendet die GetData Methode, um die Zeichenfolgendaten zu extrahieren, wenn sie vorhanden ist.

    • Verwendet einen BrushConverter, um die Zeichenfolge in eine Brush zu konvertieren.

    • Wenn die Konvertierung erfolgreich ist, wird der Pinsel auf die Fill, die die Benutzeroberfläche des Ellipse-Steuerelements Circle bereitstellt, angewendet.

    • Markiert das Drop Ereignis als behandelt. Sie sollten das Drop-Ereignis als verarbeitet markieren, damit andere Elemente, die dieses Ereignis empfangen, wissen, dass das Kreisbenutzersteuerelement es bearbeitet hat.

  3. Drücken Sie F5-, um die Anwendung zu erstellen und auszuführen.

  4. Markieren Sie den Text green in der TextBox.

  5. Ziehen Sie den Text in eine Kreissteuerung und legen Sie ihn dort ab. Der Kreis wechselt von Blau zu Grün.

    Konvertieren einer Zeichenfolge in einen Pinsel

  6. Geben Sie den Text green in das TextBox.

  7. Markieren Sie den Text gre in der TextBox.

  8. Ziehen Sie es auf ein Kreis-Steuerelement, und legen Sie es ab. Beachten Sie, dass sich der Cursor ändert, um anzugeben, dass das Ablegen zulässig ist, aber die Farbe des Kreises ändert sich nicht, da gre keine gültige Farbe ist.

  9. Ziehen Sie vom grünen Kreis-Steuerelement und lassen Sie es auf dem blauen Kreis-Steuerelement fallen. Der Kreis wechselt von Blau zu Grün. Beachten Sie, dass welcher Cursor angezeigt wird davon abhängt, ob TextBox oder der Kreis die Ziehquelle ist.

Das Festlegen der AllowDrop Eigenschaft auf true und die Verarbeitung der verworfenen Daten sind alles, was erforderlich ist, um ein Element als Dropziel zu aktivieren. Um jedoch eine bessere Benutzererfahrung zu bieten, sollten Sie auch die Ereignisse DragEnter, DragLeave und DragOver behandeln. In diesen Ereignissen können Sie Prüfungen durchführen und dem Benutzer zusätzliches Feedback geben, bevor die Daten gelöscht werden.

Wenn Daten über das Kreis-Benutzersteuerelement gezogen werden, sollte das Steuerelement die Drag-Quelle benachrichtigen, ob es die gezogenen Daten verarbeiten kann. Wenn das Steuerelement nicht weiß, wie die Daten verarbeitet werden, sollte es die Ablage ablehnen. Dazu behandeln Sie das DragOver Ereignis und legen die Effects Eigenschaft fest.

So überprüfen Sie, ob die Datenablage erlaubt ist

  1. Öffnen Sie Circle.xaml.cs oder Circle.xaml.vb.

  2. Fügen Sie die folgende OnDragOver Außerkraftsetzung hinzu, um die Klassenbehandlung für das DragOver Ereignis bereitzustellen.

    protected override void OnDragOver(DragEventArgs e)
    {
        base.OnDragOver(e);
        e.Effects = DragDropEffects.None;
    
        // If the DataObject contains string data, extract it.
        if (e.Data.GetDataPresent(DataFormats.StringFormat))
        {
            string dataString = (string)e.Data.GetData(DataFormats.StringFormat);
    
            // If the string can be converted into a Brush, allow copying or moving.
            BrushConverter converter = new BrushConverter();
            if (converter.IsValid(dataString))
            {
                // Set Effects to notify the drag source what effect
                // the drag-and-drop operation will have. These values are
                // used by the drag source's GiveFeedback event handler.
                // (Copy if CTRL is pressed; otherwise, move.)
                if (e.KeyStates.HasFlag(DragDropKeyStates.ControlKey))
                {
                    e.Effects = DragDropEffects.Copy;
                }
                else
                {
                    e.Effects = DragDropEffects.Move;
                }
            }
        }
        e.Handled = true;
    }
    
    Protected Overrides Sub OnDragOver(ByVal e As System.Windows.DragEventArgs)
        MyBase.OnDragOver(e)
        e.Effects = DragDropEffects.None
    
        ' If the DataObject contains string data, extract it.
        If e.Data.GetDataPresent(DataFormats.StringFormat) Then
            Dim dataString As String = e.Data.GetData(DataFormats.StringFormat)
    
            ' If the string can be converted into a Brush, allow copying or moving.
            Dim converter As New BrushConverter
            If converter.IsValid(dataString) Then
                ' Set Effects to notify the drag source what effect
                ' the drag-and-drop operation will have. These values are 
                ' used by the drag source's GiveFeedback event handler.
                ' (Copy if CTRL is pressed; otherwise, move.)
                If e.KeyStates.HasFlag(DragDropKeyStates.ControlKey) Then
                    e.Effects = DragDropEffects.Copy
                Else
                    e.Effects = DragDropEffects.Move
                End If
            End If
        End If
        e.Handled = True
    End Sub
    

    Diese OnDragOver Überschreibung führt die folgenden Aufgaben aus.

    • Legt die Effects-Eigenschaft auf None fest.

    • Führt dieselben Prüfungen aus, die in der OnDrop Methode ausgeführt werden, um zu bestimmen, ob das Circle-Benutzersteuerelement die gezogenen Daten verarbeiten kann.

    • Wenn das Benutzersteuerelement die Daten verarbeiten kann, legt die Effects Eigenschaft auf Copy oder Move.

  3. Drücken Sie F5-, um die Anwendung zu erstellen und auszuführen.

  4. Markieren Sie den Text gre in der TextBox.

  5. Ziehen Sie den Text auf ein Kreis-Steuerelement. Beachten Sie, dass sich der Cursor jetzt ändert, um anzugeben, dass der Drop nicht zulässig ist, da gre es sich nicht um eine gültige Farbe handelt.

Sie können die Benutzererfahrung weiter verbessern, indem Sie eine Vorschau des Drop-Vorgangs anwenden. Für das Benutzersteuerelement Kreis, überschreiben Sie die OnDragEnter- und OnDragLeave-Methode. Wenn die Daten über das Steuerelement gezogen werden, wird der aktuelle Hintergrund Fill in einer Platzhaltervariable gespeichert. Die Zeichenfolge wird dann in einen Pinsel umgewandelt und auf die Benutzeroberfläche des Kreises Ellipse angewendet. Wenn die Daten aus dem Kreis gezogen werden, ohne gelöscht zu werden, wird der ursprüngliche Fill Wert erneut auf den Kreis angewendet.

Um eine Vorschau der Effekte des Zieh-und-Lass-los-Vorgangs anzuzeigen

  1. Öffnen Sie Circle.xaml.cs oder Circle.xaml.vb.

  2. Deklarieren Sie in der Circle-Klasse eine private Brush Variable namens _previousFill und initialisieren Sie sie in null.

    public partial class Circle : UserControl
    {
        private Brush _previousFill = null;
    
    Public Class Circle
        Private _previousFill As Brush = Nothing
    
  3. Fügen Sie die folgende OnDragEnter Außerkraftsetzung hinzu, um die Klassenbehandlung für das DragEnter Ereignis bereitzustellen.

    protected override void OnDragEnter(DragEventArgs e)
    {
        base.OnDragEnter(e);
        // Save the current Fill brush so that you can revert back to this value in DragLeave.
        _previousFill = circleUI.Fill;
    
        // If the DataObject contains string data, extract it.
        if (e.Data.GetDataPresent(DataFormats.StringFormat))
        {
            string dataString = (string)e.Data.GetData(DataFormats.StringFormat);
    
            // If the string can be converted into a Brush, convert it.
            BrushConverter converter = new BrushConverter();
            if (converter.IsValid(dataString))
            {
                Brush newFill = (Brush)converter.ConvertFromString(dataString.ToString());
                circleUI.Fill = newFill;
            }
        }
    }
    
    Protected Overrides Sub OnDragEnter(ByVal e As System.Windows.DragEventArgs)
        MyBase.OnDragEnter(e)
        _previousFill = circleUI.Fill
    
        ' If the DataObject contains string data, extract it.
        If e.Data.GetDataPresent(DataFormats.StringFormat) Then
            Dim dataString As String = e.Data.GetData(DataFormats.StringFormat)
    
            ' If the string can be converted into a Brush, convert it.
            Dim converter As New BrushConverter
            If converter.IsValid(dataString) Then
                Dim newFill As Brush = converter.ConvertFromString(dataString)
                circleUI.Fill = newFill
            End If
        End If
        e.Handled = True
    End Sub
    

    Diese OnDragEnter Überschreibung führt die folgenden Aufgaben aus.

    • Speichert die Fill-Eigenschaft von Ellipse in der Variable _previousFill.

    • Führt die gleichen Prüfungen aus, die in der OnDrop Methode ausgeführt werden, um zu bestimmen, ob die Daten in eine Brushkonvertiert werden können.

    • Wenn die Daten in ein gültiges Brush konvertiert werden, wird es auf das Fill von Ellipse angewendet.

  4. Fügen Sie die folgende OnDragLeave Außerkraftsetzung hinzu, um die Klassenbehandlung für das DragLeave Ereignis bereitzustellen.

    protected override void OnDragLeave(DragEventArgs e)
    {
        base.OnDragLeave(e);
        // Undo the preview that was applied in OnDragEnter.
        circleUI.Fill = _previousFill;
    }
    
    Protected Overrides Sub OnDragLeave(ByVal e As System.Windows.DragEventArgs)
        MyBase.OnDragLeave(e)
        ' Undo the preview that was applied in OnDragEnter.
        circleUI.Fill = _previousFill
    End Sub
    

    Diese OnDragLeave Überschreibung führt die folgenden Aufgaben aus.

    • Wendet die Brush in der _previousFill Variable gespeicherte Eigenschaft auf die FillEllipse Benutzeroberfläche des Kreis-Benutzersteuerelements an.
  5. Drücken Sie F5-, um die Anwendung zu erstellen und auszuführen.

  6. Markieren Sie den Text green in der TextBox.

  7. Ziehen Sie den Text über ein Kreis-Steuerelement, ohne ihn ablegen zu müssen. Der Kreis wechselt von Blau zu Grün.

    Anzeigen einer Vorschau der Effekte eines Drag-and-Drop-Vorgangs

  8. Ziehen Sie den Text von der Kreissteuerung weg. Der Kreis wechselt von Grün zurück in Blau.

Ein Panel zum Empfang abgelegter Daten aktivieren

In diesem Abschnitt aktivieren Sie die Panels, die die Circle-Benutzersteuerelemente hosten, damit sie als Drop-Ziele für gezogene Circle-Daten dienen. Sie implementieren Code, mit dem Sie einen Kreis von einem Bereich in einen anderen verschieben oder eine Kopie eines Kreis-Steuerelements erstellen können, indem Sie beim Ziehen und Ablegen eines Kreises die STRG-TASTE gedrückt halten.

  1. Öffnen Sie "MainWindow.xaml".

  2. Wie im folgenden XAML gezeigt, fügen Sie in jedem Steuerelement StackPanel Handler für die DragOver und Drop Ereignisse hinzu. Benennen Sie den DragOver Ereignishandler, panel_DragOverund benennen Sie den Drop Ereignishandler, panel_Drop.

    Standardmäßig sind die Panels keine Ziele für Drag-and-Drop-Aktionen. Um sie zu aktivieren, fügen Sie die AllowDrop Eigenschaft beiden Bereichen hinzu, und legen Sie den Wert auf true.

    <StackPanel Grid.Column="0"
                Background="Beige"
                AllowDrop="True"
                DragOver="panel_DragOver"
                Drop="panel_Drop">
        <TextBox Width="Auto" Margin="2"
                 Text="green"/>
        <local:Circle Margin="2" />
        <local:Circle Margin="2" />
    </StackPanel>
    <StackPanel Grid.Column="1"
                Background="Bisque"
                AllowDrop="True"
                DragOver="panel_DragOver"
                Drop="panel_Drop">
    </StackPanel>
    
  3. Öffnen Sie MainWindows.xaml.cs oder MainWindow.xaml.vb.

  4. Fügen Sie den folgenden Code für den DragOver Ereignishandler hinzu.

    private void panel_DragOver(object sender, DragEventArgs e)
    {
        if (e.Data.GetDataPresent("Object"))
        {
            // These Effects values are used in the drag source's
            // GiveFeedback event handler to determine which cursor to display.
            if (e.KeyStates == DragDropKeyStates.ControlKey)
            {
                e.Effects = DragDropEffects.Copy;
            }
            else
            {
                e.Effects = DragDropEffects.Move;
            }
        }
    }
    
    Private Sub panel_DragOver(ByVal sender As System.Object, ByVal e As System.Windows.DragEventArgs)
        If e.Data.GetDataPresent("Object") Then
            ' These Effects values are used in the drag source's
            ' GiveFeedback event handler to determine which cursor to display.
            If e.KeyStates = DragDropKeyStates.ControlKey Then
                e.Effects = DragDropEffects.Copy
            Else
                e.Effects = DragDropEffects.Move
            End If
        End If
    End Sub
    

    Dieser DragOver Ereignishandler führt die folgenden Aufgaben aus:

    • Überprüft, ob die gezogenen Daten die Objekt-Daten enthalten, die in DataObject vom Circle-Benutzersteuerelement verpackt und im Aufruf zu DoDragDrop übergeben wurden.

    • Wenn die "Objekt"-Daten vorhanden sind, überprüft sie, ob die STRG-TASTE gedrückt wird.

    • Wenn die STRG-Taste gedrückt wird, wird die Effects-Eigenschaft auf Copy gesetzt. Legen Sie andernfalls die Effects Eigenschaft auf Move.

  5. Fügen Sie den folgenden Code für den Drop Ereignishandler hinzu.

    private void panel_Drop(object sender, DragEventArgs e)
    {
        // If an element in the panel has already handled the drop,
        // the panel should not also handle it.
        if (e.Handled == false)
        {
            Panel _panel = (Panel)sender;
            UIElement _element = (UIElement)e.Data.GetData("Object");
    
            if (_panel != null && _element != null)
            {
                // Get the panel that the element currently belongs to,
                // then remove it from that panel and add it the Children of
                // the panel that its been dropped on.
                Panel _parent = (Panel)VisualTreeHelper.GetParent(_element);
    
                if (_parent != null)
                {
                    if (e.KeyStates == DragDropKeyStates.ControlKey &&
                        e.AllowedEffects.HasFlag(DragDropEffects.Copy))
                    {
                        Circle _circle = new Circle((Circle)_element);
                        _panel.Children.Add(_circle);
                        // set the value to return to the DoDragDrop call
                        e.Effects = DragDropEffects.Copy;
                    }
                    else if (e.AllowedEffects.HasFlag(DragDropEffects.Move))
                    {
                        _parent.Children.Remove(_element);
                        _panel.Children.Add(_element);
                        // set the value to return to the DoDragDrop call
                        e.Effects = DragDropEffects.Move;
                    }
                }
            }
        }
    }
    
    Private Sub panel_Drop(ByVal sender As System.Object, ByVal e As System.Windows.DragEventArgs)
        ' If an element in the panel has already handled the drop,
        ' the panel should not also handle it.
        If e.Handled = False Then
            Dim _panel As Panel = sender
            Dim _element As UIElement = e.Data.GetData("Object")
    
            If _panel IsNot Nothing And _element IsNot Nothing Then
                ' Get the panel that the element currently belongs to,
                ' then remove it from that panel and add it the Children of
                ' the panel that its been dropped on.
    
                Dim _parent As Panel = VisualTreeHelper.GetParent(_element)
                If _parent IsNot Nothing Then
                    If e.KeyStates = DragDropKeyStates.ControlKey And _
                        e.AllowedEffects.HasFlag(DragDropEffects.Copy) Then
                        Dim _circle As New Circle(_element)
                        _panel.Children.Add(_circle)
                        ' set the value to return to the DoDragDrop call
                        e.Effects = DragDropEffects.Copy
                    ElseIf e.AllowedEffects.HasFlag(DragDropEffects.Move) Then
                        _parent.Children.Remove(_element)
                        _panel.Children.Add(_element)
                        ' set the value to return to the DoDragDrop call
                        e.Effects = DragDropEffects.Move
                    End If
                End If
            End If
        End If
    End Sub
    

    Dieser Drop Ereignishandler führt die folgenden Aufgaben aus:

    • Überprüft, ob das Drop Ereignis bereits behandelt wurde. Wenn beispielsweise ein Kreis auf einen anderen Kreis fällt, der das Drop Ereignis behandelt, soll das Panel, das den zweiten Kreis enthält, das Ereignis nicht ebenfalls behandeln.

    • Wenn das Drop-Ereignis nicht behandelt wird, wird überprüft, ob die Strg-Taste gedrückt wird.

    • Wenn die STRG-TASTE gedrückt wird, wenn dies Drop geschieht, wird eine Kopie der Kreissteuerung erstellt und der Children-Sammlung von StackPanel hinzugefügt.

    • Wenn die Strg-Taste nicht gedrückt wird, verschiebt sich der Kreis aus der Children Sammlung des übergeordneten Bereichs in die Children Sammlung des Bereichs, auf dem er abgelegt wurde.

    • Legt die Effects-Eigenschaft fest, um die DoDragDrop-Methode zu benachrichtigen, ob ein Verschiebungs- oder Kopiervorgang ausgeführt wurde.

  6. Drücken Sie F5-, um die Anwendung zu erstellen und auszuführen.

  7. Wählen Sie den Text green aus dem TextBox.

  8. Ziehen Sie den Text über eine Kreissteuerung und lassen Sie ihn dort fallen.

  9. Ziehen Sie ein Kreissteuerungselement aus dem linken Bereich auf den rechten Bereich und lassen Sie es los. Der Kreis wird aus der Children-Sammlung des linken Panels entfernt und zur Children-Sammlung des rechten Panels hinzugefügt.

  10. Ziehen Sie ein Kreis-Steuerelement aus dem einen Bereich in den anderen Bereich und legen Sie es ab, während Sie die Strg-Taste drücken. Der Kreis wird kopiert und die Kopie wird der Children Kollektion des empfangenden Panels hinzugefügt.

    Ziehen eines Kreises beim Drücken der STRG-TASTE

Siehe auch