Share via


Procedura dettagliata: abilitare il trascinamento della selezione in un controllo utente

Questa procedura dettagliata illustra come creare un controllo utente personalizzato che può partecipare al trasferimento dei dati di trascinamento della selezione in Windows Presentation Foundation (WPF).

In questa procedura dettagliata verrà creato un wpf UserControl personalizzato che rappresenta una forma circolare. Si implementeranno funzionalità nel controllo per consentire il trasferimento di dati tramite trascinamento. Ad esempio, se si trascina da un controllo Circle a un altro, i dati del colore di riempimento vengono copiati dal controllo Circle di origine a quello di destinazione. Se si trascina da un controllo Circle a un TextBoxoggetto , la rappresentazione di stringa del colore Riempimento viene copiata in TextBox. Si creerà anche una piccola applicazione che contiene due controlli pannello e un oggetto TextBox per testare la funzionalità di trascinamento della selezione. Si scriverà codice che consente ai pannelli di elaborare i dati Circle rilasciati per permettere di spostare o copiare cerchi dalla raccolta Children di un pannello all'altro.

In questa procedura dettagliata sono illustrati i task seguenti:

  • Creare un controllo utente personalizzato.

  • Consentire al controllo utente di essere un'origine di trascinamento.

  • Consentire al controllo utente di essere un obiettivo di rilascio.

  • Consentire a un pannello di ricevere dati rilasciati dal controllo utente.

Prerequisiti

Per completare la procedura dettagliata, è necessario Visual Studio.

Creare il progetto dell'applicazione

In questa sezione si creerà l'infrastruttura dell'applicazione, che include una pagina principale con due pannelli e un .TextBox

  1. Creare un nuovo progetto di applicazione WPF in Visual Basic o Visual C# denominato DragDropExample. Per altre informazioni, vedere Procedura dettagliata: La prima applicazione desktop WPF.

  2. Aprire MainWindow.xaml.

  3. Aggiungere il markup seguente tra i tag di apertura e chiusura Grid .

    Questo markup crea l'interfaccia utente per l'applicazione di prova.

    <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>
    

Aggiungere un nuovo controllo utente al progetto

In questa sezione si aggiungerà un nuovo controllo utente al progetto.

  1. Scegliere Aggiungi controllo utente dal menu Progetto.

  2. Nella finestra di dialogo Aggiungi nuovo elemento modificare il nome in Circle.xamle fare clic su Aggiungi.

    Circle.xaml e il relativo code-behind vengono aggiunti al progetto.

  3. Aprire Circle.xaml.

    Questo file conterrà gli elementi dell'interfaccia utente del controllo utente.

  4. Aggiungere il markup seguente alla radice Grid per creare un semplice controllo utente con un cerchio blu come interfaccia utente.

    <Ellipse x:Name="circleUI" 
             Height="100" Width="100"
             Fill="Blue" />
    
  5. Aprire Circle.xaml.cs o Circle.xaml.vb.

  6. In C# aggiungere il codice seguente dopo il costruttore senza parametri per creare un costruttore di copia. In Visual Basic aggiungere il codice seguente per creare sia un costruttore senza parametri che un costruttore di copia.

    Per consentire la copia del controllo utente, aggiungere un metodo di costruttore di copia nel file code-behind. Nel controllo utente Circle semplificato si copieranno solo il riempimento e le dimensioni del controllo utente.

    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
    

Aggiungere il controllo utente alla finestra principale

  1. Aprire MainWindow.xaml.

  2. Aggiungere il codice XAML seguente al tag di apertura Window per creare un riferimento allo spazio dei nomi XML all'applicazione corrente.

    xmlns:local="clr-namespace:DragDropExample"
    
  3. Nel primo StackPanel, aggiungere il codice XAML seguente per creare due istanze del controllo utente Circle nel primo pannello.

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

    Il codice XAML completo per il pannello è analogo al seguente.

    <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>
    

Implementare eventi di origine di trascinamento nel controllo utente

In questa sezione si eseguirà l'override del OnMouseMove metodo e si avvierà l'operazione di trascinamento della selezione.

Se viene avviato un trascinamento (viene premuto un pulsante del mouse e il mouse viene spostato), i dati da trasferire in un oggetto DataObjectverranno inseriti nel pacchetto . In questo caso, il controllo Circle assemblerà tre elementi di dati: una rappresentazione di stringa del colore di riempimento, una rappresentazione doppia dell'altezza e una copia di se stesso.

Per avviare un'operazione di riempimento

  1. Aprire Circle.xaml.cs o Circle.xaml.vb.

  2. Aggiungere l'override seguente OnMouseMove per fornire la gestione delle classi per l'evento MouseMove .

    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
    

    Questa OnMouseMove override esegue le attività seguenti:

    • Controlla se il pulsante sinistro del mouse viene premuto mentre il mouse è in movimento.

    • Inserisce i dati Circle in un oggetto DataObject. In questo caso, il controllo Circle assembla tre elementi dati: una rappresentazione di stringa del colore di riempimento, una rappresentazione doppia dell'altezza e una copia di se stesso.

    • Chiama il metodo statico DragDrop.DoDragDrop per avviare l'operazione di trascinamento della selezione. Passare i tre parametri seguenti al DoDragDrop metodo :

      • dragSource - Un riferimento a questo controllo.

      • data : oggetto DataObject creato nel codice precedente.

      • allowedEffects : le operazioni di trascinamento consentite, ovvero Copy o Move.

  3. Premere F5 per compilare ed eseguire l'applicazione.

  4. Fare clic su uno dei controlli Circle e trascinarlo sui pannelli, sull'altro Circle e sull'oggetto TextBox. Quando si trascina su TextBox, il cursore cambia per indicare uno spostamento.

  5. Durante il trascinamento di un cerchio su TextBox, premere CTRL. Notare come il cursore cambia aspetto per indicare una copia.

  6. Trascinare e rilasciare un oggetto Circle nell'oggetto TextBox. La rappresentazione di stringa del colore di riempimento del cerchio viene aggiunta all'oggetto TextBox.

    String representation of Circle's fill color

Per impostazione predefinita, il cursore cambierà aspetto durante un'operazione di trascinamento per indicare l'effetto che avrà il rilascio dei dati. È possibile personalizzare il feedback fornito all'utente gestendo l'evento GiveFeedback e impostando un cursore diverso.

Inviare commenti e suggerimenti all'utente

  1. Aprire Circle.xaml.cs o Circle.xaml.vb.

  2. Aggiungere l'override seguente OnGiveFeedback per fornire la gestione delle classi per l'evento GiveFeedback .

    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
    

    Questa OnGiveFeedback override esegue le attività seguenti:

    • Controlla i Effects valori impostati nel gestore eventi della destinazione di DragOver rilascio.

    • Imposta un cursore personalizzato in base al Effects valore . Il cursore ha lo scopo di fornire un feedback visivo all'utente sull'effetto che avrà il rilascio dei dati.

  3. Premere F5 per compilare ed eseguire l'applicazione.

  4. Trascinare uno dei controlli Circle sui pannelli, l'altro Circle e .TextBox Si noti che i cursori sono ora i cursori personalizzati specificati nell'override OnGiveFeedback .

    Drag and drop with custom cursors

  5. Selezionare il testo green da TextBox.

  6. Trascinare il testo green su un controllo Circle. Notare che vengono visualizzati i cursori predefiniti per indicare gli effetti dell'operazione di trascinamento. Il cursore di feedback viene sempre impostato dall'origine di trascinamento.

Implementare eventi di destinazione di rilascio nel controllo utente

In questa sezione si specificherà che il controllo utente è un obiettivo di rilascio, si eseguirà l'override dei metodi che consentono al controllo utente di essere un obiettivo di rilascio e si elaboreranno i dati rilasciati sul controllo.

Per consentire al controllo utente di essere un obiettivo di rilascio

  1. Aprire Circle.xaml.

  2. Nel tag di apertura UserControl aggiungere la AllowDrop proprietà e impostarla su 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">
    

Il OnDrop metodo viene chiamato quando la AllowDrop proprietà è impostata su true e i dati dell'origine di trascinamento vengono rilasciati nel controllo utente Circle. In questo metodo si elaboreranno i dati rilasciati e li si applicheranno al controllo Circle.

Per elaborare i dati rilasciati

  1. Aprire Circle.xaml.cs o Circle.xaml.vb.

  2. Aggiungere l'override seguente OnDrop per fornire la gestione delle classi per l'evento Drop .

    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
    

    Questa OnDrop override esegue le attività seguenti:

    • Usa il GetDataPresent metodo per verificare se i dati trascinati contengono un oggetto stringa.

    • Usa il GetData metodo per estrarre i dati stringa, se presenti.

    • Usa un BrushConverter oggetto per tentare di convertire la stringa in un oggetto Brush.

    • Se la conversione ha esito positivo, applica il pennello a Fill di Ellipse che fornisce l'interfaccia utente del controllo Circle.

    • Contrassegna l'evento Drop come gestito. È necessario contrassegnare l'evento di trascinamento come gestito per segnalare agli altri elementi che ricevono l'evento che questo è stato gestito dal controllo utente Circle.

  3. Premere F5 per compilare ed eseguire l'applicazione.

  4. Selezionare il testo green in TextBox.

  5. Trascinare il testo su un controllo Circle e rilasciarlo. Il controllo Circle passa da blu a verde.

    Convert a string to a brush

  6. Digitare il testo green in TextBox.

  7. Selezionare il testo gre in TextBox.

  8. Trascinarlo su un controllo Circle e rilasciarlo. Notare che il cursore cambia aspetto per indicare che è consentito il trascinamento ma il colore del controllo Circle non cambia poiché gre non è un colore valido.

  9. Trascinare dal controllo Circle verde e rilasciare sul controllo Circle blu. Il controllo Circle passa da blu a verde. Si noti che il cursore visualizzato dipende dal fatto TextBox che o Circle sia l'origine di trascinamento.

L'impostazione della AllowDrop proprietà su true ed elaborazione dei dati eliminati è tutto ciò che è necessario per consentire a un elemento di essere una destinazione di rilascio. Tuttavia, per offrire un'esperienza utente migliore, è necessario gestire anche gli DragEntereventi , DragLeavee DragOver . In questi eventi, è possibile eseguire controlli e offrire feedback all'utente prima che i dati vengono rilasciati.

Quando i dati vengono rilasciati sul controllo utente Circle, il controllo deve notificare all'origine di trascinamento se può elaborare i dati trascinati. Se il controllo non è in grado di elaborare i dati, deve rifiutare il rilascio. A tale scopo, si gestirà l'evento DragOver e si imposta la Effects proprietà .

Per verificare se il rilascio dei dati è consentito

  1. Aprire Circle.xaml.cs o Circle.xaml.vb.

  2. Aggiungere l'override seguente OnDragOver per fornire la gestione delle classi per l'evento DragOver .

    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
    

    Questa OnDragOver override esegue le attività seguenti:

    • Imposta la proprietà Effects su None.

    • Esegue gli stessi controlli eseguiti nel OnDrop metodo per determinare se il controllo utente Circle può elaborare i dati trascinati.

    • Se il controllo utente può elaborare i dati, imposta la Effects proprietà su Copy o Move.

  3. Premere F5 per compilare ed eseguire l'applicazione.

  4. Selezionare il testo gre in TextBox.

  5. Trascinare il testo su un controllo Circle. Notare che ora il cursore cambia aspetto per indicare che il trascinamento non è consentito poiché gre non è un colore valido.

È possibile migliorare ulteriormente l'esperienza utente applicando un'anteprima dell'operazione di trascinamento. Per il controllo utente Circle, si eseguirà l'override dei OnDragEnter metodi e OnDragLeave . Quando i dati vengono trascinati sul controllo, lo sfondo Fill corrente viene salvato in una variabile segnaposto. La stringa viene quindi convertita in un pennello e applicata all'oggetto Ellipse che fornisce l'interfaccia utente di Circle. Se i dati vengono trascinati all'esterno di Circle senza essere eliminati, il valore originale Fill viene nuovamente applicato al circle.

Per visualizzare in anteprima gli effetti dell'operazione di trascinamento

  1. Aprire Circle.xaml.cs o Circle.xaml.vb.

  2. Nella classe Circle dichiarare una variabile privata Brush denominata _previousFill e inizializzarla in null.

    public partial class Circle : UserControl
    {
        private Brush _previousFill = null;
    
    Public Class Circle
        Private _previousFill As Brush = Nothing
    
  3. Aggiungere l'override seguente OnDragEnter per fornire la gestione delle classi per l'evento DragEnter .

    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
    

    Questa OnDragEnter override esegue le attività seguenti:

    • Salva la Fill proprietà di Ellipse nella _previousFill variabile .

    • Esegue gli stessi controlli eseguiti nel OnDrop metodo per determinare se i dati possono essere convertiti in un oggetto Brush.

    • Se i dati vengono convertiti in un oggetto valido Brush, lo applica all'oggetto FillEllipsedi .

  4. Aggiungere l'override seguente OnDragLeave per fornire la gestione delle classi per l'evento DragLeave .

    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
    

    Questa OnDragLeave override esegue le attività seguenti:

    • Applica l'oggetto Brush salvato nella _previousFill variabile a Fill di Ellipse che fornisce l'interfaccia utente del controllo utente Circle.
  5. Premere F5 per compilare ed eseguire l'applicazione.

  6. Selezionare il testo green in TextBox.

  7. Trascinare il testo su un controllo Circle senza rilasciarlo. Il controllo Circle passa da blu a verde.

    Preview the effects of a drag-and-drop operation

  8. Trascinare il testo dal controllo Circle. Il controllo Circle passa da verde a blu.

Abilitare un pannello per ricevere dati eliminati

In questa sezione si abilitano i pannelli che ospitano i controlli utente Circle per agire come destinazioni di rilascio per i dati Circle trascinati. Si implementerà il codice che consente di spostare un cerchio da un pannello a un altro o di creare una copia di un controllo Circle tenendo premuto ctrl mentre trascina e rilascia un cerchio.

  1. Aprire MainWindow.xaml.

  2. Come illustrato nel codice XAML seguente, in ognuno dei StackPanel controlli aggiungere gestori per gli DragOver eventi e Drop . Denominare il DragOver gestore eventi, panel_DragOvere denominare il Drop gestore eventi, panel_Drop.

    Per impostazione predefinita, i pannelli non rilasciano destinazioni. Per abilitarle, aggiungere la AllowDrop proprietà a entrambi i pannelli e impostare il valore su 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. Aprire MainWindows.xaml.cs o MainWindow.xaml.vb.

  4. Aggiungere il codice seguente per il DragOver gestore eventi.

    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
    

    Questo DragOver gestore eventi esegue le attività seguenti:

    • Verifica che i dati trascinati contengano i dati "Object" inclusi nel pacchetto nel DataObject controllo utente Circle e passati alla chiamata a DoDragDrop.

    • Se i dati "Object" sono presenti, controlla se il tasto CTRL viene premuto.

    • Se il tasto CTRL viene premuto, imposta la Effects proprietà su Copy. In caso contrario, impostare la Effects proprietà su Move.

  5. Aggiungere il codice seguente per il Drop gestore eventi.

    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
    

    Questo Drop gestore eventi esegue le attività seguenti:

    • Controlla se l'evento Drop è già stato gestito. Ad esempio, se un Circle viene eliminato su un altro Circle che gestisce l'evento Drop , non si vuole che anche il pannello che contiene circle lo gestisca.

    • Se l'evento Drop non viene gestito, controlla se il tasto CTRL viene premuto.

    • Se il tasto CTRL viene premuto quando Drop si verifica , crea una copia del controllo Circle e la aggiunge all'insieme Children dell'oggetto StackPanel.

    • Se il tasto CTRL non viene premuto, sposta circle dall'insieme Children del relativo pannello padre all'insieme Children del pannello su cui è stato eliminato.

    • Imposta la Effects proprietà per notificare al DoDragDrop metodo se è stata eseguita un'operazione di spostamento o copia.

  6. Premere F5 per compilare ed eseguire l'applicazione.

  7. Selezionare il testo green da TextBox.

  8. Trascinare il testo su un controllo Circle e rilasciarlo.

  9. Trascinare un controllo Circle dal pannello di sinistra al pannello di destra e rilasciarlo. Circle viene rimosso dall'insieme Children del pannello sinistro e aggiunto all'insieme Children del pannello di destra.

  10. Trascinare un controllo Circle dal pannello in cui si trova nell'altro pannello e rilasciarlo mentre si preme CTRL . Circle viene copiato e la copia viene aggiunta alla Children raccolta del pannello ricevente.

    Dragging a Circle while pressing the CTRL key

Vedi anche