Udostępnij za pośrednictwem


Wskazówki: włączanie przeciągania i upuszczania w kontrolce użytkownika

W tym przewodniku pokazano, jak utworzyć niestandardową kontrolkę użytkownika, która może uczestniczyć w przeciąganiu i upuszczaniu transferu danych w programie Windows Presentation Foundation (WPF).

W tym przewodniku utworzysz niestandardowy WPF UserControl reprezentujący kształt okręgu. Zaimplementujesz funkcje kontrolki, aby umożliwić transfer danych przez przeciąganie i upuszczanie. Jeśli na przykład przeciągniesz z jednej kontrolki Circle do innej, dane koloru wypełnienia są kopiowane ze źródłowego okręgu do miejsca docelowego. Jeśli przeciągniesz kontrolkę TextBoxCircle do elementu , ciąg reprezentujący kolor wypełnienia zostanie skopiowany do TextBoxelementu . Utworzysz również małą aplikację zawierającą dwa kontrolki panelu i element , TextBox aby przetestować funkcję przeciągania i upuszczania. Napiszesz kod, który umożliwia panelom przetwarzanie porzuconych danych Circle, co umożliwi przenoszenie lub kopiowanie okręgów z kolekcji Podrzędne jednego panelu do drugiego.

W instruktażu przedstawiono następujące zagadnienia:

  • Utwórz niestandardową kontrolkę użytkownika.

  • Umożliwianie kontrolki użytkownika jako źródła przeciągania.

  • Włącz kontrolkę użytkownika jako element docelowy upuszczania.

  • Umożliwia panelowi odbieranie danych porzuconych z kontrolki użytkownika.

Wymagania wstępne

Aby ukończyć ten przewodnik, potrzebny jest program Visual Studio.

Tworzenie projektu aplikacji

W tej sekcji utworzysz infrastrukturę aplikacji zawierającą stronę główną z dwoma panelami i .TextBox

  1. Utwórz nowy projekt aplikacji WPF w Visual Basic lub Visual C# o nazwie DragDropExample. Aby uzyskać więcej informacji, zobacz Przewodnik: Moja pierwsza aplikacja klasyczna WPF.

  2. Otwórz plik MainWindow.xaml.

  3. Dodaj następujący znacznik między tagami otwierania i zamykania Grid .

    Ten znacznik tworzy interfejs użytkownika dla aplikacji testowej.

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

Dodawanie nowej kontrolki użytkownika do projektu

W tej sekcji dodasz nową kontrolkę użytkownika do projektu.

  1. W menu Project (Projekt) wybierz pozycję Add User Control (Dodaj kontrolkę użytkownika).

  2. W oknie dialogowym Dodawanie nowego elementu zmień nazwę na Circle.xaml, a następnie kliknij przycisk Dodaj.

    Plik Circle.xaml i jego kod-behind są dodawane do projektu.

  3. Otwórz plik Circle.xaml.

    Ten plik będzie zawierać elementy interfejsu użytkownika kontrolki użytkownika.

  4. Dodaj następujący znacznik do katalogu głównego Grid , aby utworzyć prostą kontrolkę użytkownika, która ma niebieski okrąg jako interfejs użytkownika.

    <Ellipse x:Name="circleUI" 
             Height="100" Width="100"
             Fill="Blue" />
    
  5. Otwórz plik Circle.xaml.cs lub Circle.xaml.vb.

  6. W języku C# dodaj następujący kod po konstruktorze bez parametrów, aby utworzyć konstruktor kopiujący. W języku Visual Basic dodaj następujący kod, aby utworzyć zarówno konstruktor bez parametrów, jak i konstruktor kopiujący.

    Aby umożliwić skopiowanie kontrolki użytkownika, należy dodać metodę konstruktora kopiowania w pliku za pomocą kodu. W uproszczonej kontrolce użytkownika Circle skopiujesz tylko kontrolkę Fill i rozmiar kontrolki użytkownika.

    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
    

Dodawanie kontrolki użytkownika do okna głównego

  1. Otwórz plik MainWindow.xaml.

  2. Dodaj następujący kod XAML do tagu otwierającego Window , aby utworzyć odwołanie przestrzeni nazw XML do bieżącej aplikacji.

    xmlns:local="clr-namespace:DragDropExample"
    
  3. W pierwszym StackPanelpliku dodaj następujący kod XAML, aby utworzyć dwa wystąpienia kontrolki użytkownika Circle w pierwszym panelu.

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

    Pełny kod XAML dla panelu wygląda następująco.

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

Implementowanie przeciągania zdarzeń źródłowych w kontrolce użytkownika

W tej sekcji zastąpisz metodę OnMouseMove i zainicjujesz operację przeciągania i upuszczania.

Jeśli przeciągnięcie zostanie uruchomione (naciśnięcie przycisku myszy i przeniesienie myszy), spakujesz dane, które mają zostać przeniesione do DataObjectelementu . W takim przypadku kontrolka Circle spakuje trzy elementy danych; reprezentacja ciągu koloru wypełnienia, podwójna reprezentacja wysokości i kopia samego siebie.

Aby zainicjować operację przeciągania i upuszczania

  1. Otwórz plik Circle.xaml.cs lub Circle.xaml.vb.

  2. Dodaj następujące OnMouseMove przesłonięcia, aby zapewnić obsługę klas dla MouseMove zdarzenia.

    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
    

    To OnMouseMove zastąpienie wykonuje następujące zadania:

    • Sprawdza, czy lewy przycisk myszy jest naciśnięty podczas przesuwania myszy.

    • Pakuje dane Circle do obiektu DataObject. W takim przypadku kontrolka Circle pakuje trzy elementy danych; reprezentacja ciągu koloru wypełnienia, podwójna reprezentacja wysokości i kopia samego siebie.

    • Wywołuje metodę statyczną DragDrop.DoDragDrop , aby zainicjować operację przeciągania i upuszczania. Do metody należy przekazać DoDragDrop następujące trzy parametry:

      • dragSource — odwołanie do tej kontrolki.

      • data — utworzony DataObject w poprzednim kodzie.

      • allowedEffects — dozwolone operacje przeciągania i upuszczania, które są Copy lub Move.

  3. Naciśnij klawisz F5, aby skompilować i uruchomić aplikację.

  4. Kliknij jedną z kontrolek Circle i przeciągnij ją na panele, drugi okrąg i TextBox. Podczas przeciągania kursora TextBoxzmienia się, aby wskazać przeniesienie.

  5. Przeciągając okrąg nad klawiszem TextBox, naciśnij klawisz Ctrl . Zwróć uwagę, że kursor zmienia się, aby wskazać kopię.

  6. Przeciągnij i upuść okrąg na .TextBox Ciąg reprezentujący kolor wypełnienia circle jest dołączany do elementu TextBox.

    String representation of Circle's fill color

Domyślnie kursor zmieni się podczas operacji przeciągania i upuszczania, aby wskazać, jaki będzie efekt upuszczania danych. Opinie przekazane użytkownikowi można dostosować, obsługując GiveFeedback zdarzenie i ustawiając inny kursor.

Prześlij opinię użytkownikowi

  1. Otwórz plik Circle.xaml.cs lub Circle.xaml.vb.

  2. Dodaj następujące OnGiveFeedback przesłonięcia, aby zapewnić obsługę klas dla GiveFeedback zdarzenia.

    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
    

    To OnGiveFeedback zastąpienie wykonuje następujące zadania:

    • Effects Sprawdza wartości ustawione w procedurze obsługi zdarzeń obiektu docelowego DragOver upuszczania.

    • Ustawia kursor niestandardowy na Effects podstawie wartości. Kursor ma na celu przekazanie użytkownikowi opinii o tym, jaki będzie efekt porzucania danych.

  3. Naciśnij klawisz F5, aby skompilować i uruchomić aplikację.

  4. Przeciągnij jeden z kontrolek Circle nad panelami, drugim okręgiem TextBoxi . Zwróć uwagę, że kursory są teraz niestandardowymi kursorami określonymi w zastąpieniu OnGiveFeedback .

    Drag and drop with custom cursors

  5. Wybierz tekst green z pliku TextBox.

  6. Przeciągnij green tekst do kontrolki Okrąg. Zwróć uwagę, że domyślne kursory są wyświetlane w celu wskazania efektów operacji przeciągania i upuszczania. Kursor opinii jest zawsze ustawiany przez źródło przeciągania.

Implementowanie zdarzeń miejsca docelowego upuszczania w kontrolce użytkownika

W tej sekcji określisz, że kontrolka użytkownika jest elementem docelowym upuszczania, przesłania metody, które umożliwiają użytkownikowi upuszczanie elementu docelowego i przetwarzanie danych, które są na nim porzucone.

Aby umożliwić użytkownikowi kontrolowanie jako cel upuszczania

  1. Otwórz plik Circle.xaml.

  2. W tagu otwierającym UserControl dodaj AllowDrop właściwość i ustaw ją na 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">
    

Metoda OnDrop jest wywoływana, gdy AllowDrop właściwość jest ustawiona na true , a dane ze źródła przeciągania są porzucane w kontrolce użytkownika Circle. W tej metodzie przetworzysz dane, które zostały porzucone i zastosujesz dane do okręgu.

Przetwarzanie porzuconych danych

  1. Otwórz plik Circle.xaml.cs lub Circle.xaml.vb.

  2. Dodaj następujące OnDrop przesłonięcia, aby zapewnić obsługę klas dla Drop zdarzenia.

    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
    

    To OnDrop zastąpienie wykonuje następujące zadania:

    • GetDataPresent Używa metody do sprawdzania, czy przeciągane dane zawierają obiekt ciągu.

    • GetData Używa metody do wyodrębniania danych ciągu, jeśli są obecne.

    • Używa wartości , BrushConverter aby spróbować przekonwertować ciąg na Brush.

    • Jeśli konwersja zakończy się pomyślnie, zastosuj szczotkę do Fill kontrolki Ellipse , która udostępnia interfejs użytkownika kontrolki Circle.

    • Drop Oznacza zdarzenie jako obsługiwane. Należy oznaczyć zdarzenie upuszczania jako obsługiwane, aby inne elementy odbierające to zdarzenie wiedziały, że kontrolka użytkownika Circle obsłużyła to zdarzenie.

  3. Naciśnij klawisz F5, aby skompilować i uruchomić aplikację.

  4. Zaznacz tekst green w pliku TextBox.

  5. Przeciągnij tekst do kontrolki Okrąg i upuść go. Okrąg zmienia się z niebieskiego na zielony.

    Convert a string to a brush

  6. Wpisz tekst green w pliku TextBox.

  7. Zaznacz tekst gre w pliku TextBox.

  8. Przeciągnij ją do kontrolki Okrąg i upuść ją. Zwróć uwagę, że kursor zmienia się, aby wskazać, że upuszczanie jest dozwolone, ale kolor okręgu nie zmienia się, ponieważ gre nie jest prawidłowym kolorem.

  9. Przeciągnij z zielonej kontrolki Circle i upuść ją na niebieskim kontrolce Circle. Okrąg zmienia się z niebieskiego na zielony. Zwróć uwagę, że wyświetlany kursor zależy od tego, czy TextBox obiekt lub okrąg jest źródłem przeciągania.

AllowDrop Ustawienie właściwości na true wartość i przetwarzanie porzuconych danych jest wymagane, aby umożliwić elementowi upuszczanie elementu docelowego. Jednak aby zapewnić lepsze środowisko użytkownika, należy również obsługiwać DragEnterzdarzenia , DragLeavei DragOver . W tych zdarzeniach można przeprowadzić kontrole i przekazać użytkownikowi dodatkową opinię, zanim dane zostaną porzucone.

Gdy dane są przeciągane przez kontrolkę użytkownika Circle, kontrolka powinna powiadomić źródło przeciągania, czy może przetwarzać przeciągane dane. Jeśli kontrolka nie wie, jak przetwarzać dane, powinna odmówić upuszczania. W tym celu obsłużysz DragOver zdarzenie i ustawisz Effects właściwość .

Aby sprawdzić, czy upuszczanie danych jest dozwolone

  1. Otwórz plik Circle.xaml.cs lub Circle.xaml.vb.

  2. Dodaj następujące OnDragOver przesłonięcia, aby zapewnić obsługę klas dla DragOver zdarzenia.

    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
    

    To OnDragOver zastąpienie wykonuje następujące zadania:

    • Effects Ustawia właściwość na None.

    • Wykonuje te same kontrole, które są wykonywane w metodzie OnDrop , aby określić, czy kontrolka użytkownika Circle może przetwarzać przeciągane dane.

    • Jeśli kontrolka użytkownika może przetwarzać dane, ustawia Effects właściwość na Copy lub Move.

  3. Naciśnij klawisz F5, aby skompilować i uruchomić aplikację.

  4. Zaznacz tekst gre w pliku TextBox.

  5. Przeciągnij tekst do kontrolki Okrąg. Zwróć uwagę, że kursor teraz zmienia się, aby wskazać, że upuszczanie jest niedozwolone, ponieważ gre nie jest prawidłowym kolorem.

Możesz jeszcze bardziej ulepszyć środowisko użytkownika, stosując podgląd operacji upuszczania. W przypadku kontrolki użytkownika Circle zastąpisz OnDragEnter metody i OnDragLeave . Gdy dane są przeciągane przez kontrolkę, bieżące tło Fill jest zapisywane w zmiennej zastępczej. Ciąg jest następnie konwertowany na szczotkę i stosowany do Ellipse interfejsu użytkownika circle. Jeśli dane są przeciągane z okręgu bez porzucania, oryginalna Fill wartość zostanie ponownie zastosowana do okręgu.

Aby wyświetlić podgląd efektów operacji przeciągania i upuszczania

  1. Otwórz plik Circle.xaml.cs lub Circle.xaml.vb.

  2. W klasie Circle zadeklaruj zmienną prywatną Brush o nazwie _previousFill i zainicjuj ją na null.

    public partial class Circle : UserControl
    {
        private Brush _previousFill = null;
    
    Public Class Circle
        Private _previousFill As Brush = Nothing
    
  3. Dodaj następujące OnDragEnter przesłonięcia, aby zapewnić obsługę klas dla DragEnter zdarzenia.

    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
    

    To OnDragEnter zastąpienie wykonuje następujące zadania:

    • Fill Zapisuje właściwość Ellipse w zmiennej _previousFill .

    • Wykonuje te same kontrole, które są wykonywane w metodzie OnDrop , aby określić, czy dane można przekonwertować na Brush.

    • Jeśli dane są konwertowane na prawidłowy Brushelement , stosuje je do Fill elementu Ellipse.

  4. Dodaj następujące OnDragLeave przesłonięcia, aby zapewnić obsługę klas dla DragLeave zdarzenia.

    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
    

    To OnDragLeave zastąpienie wykonuje następujące zadania:

    • Brush Stosuje wartość zapisaną w zmiennej _previousFill do FillEllipse zmiennej , która udostępnia interfejs użytkownika kontrolki Circle użytkownika.
  5. Naciśnij klawisz F5, aby skompilować i uruchomić aplikację.

  6. Zaznacz tekst green w pliku TextBox.

  7. Przeciągnij tekst nad kontrolką Circle bez upuszczania. Okrąg zmienia się z niebieskiego na zielony.

    Preview the effects of a drag-and-drop operation

  8. Przeciągnij tekst z dala od kontrolki Circle. Okrąg zmienia się z zielonego z powrotem na niebieski.

Włączanie panelu odbierania porzuconych danych

W tej sekcji włączysz panele obsługujące kontrolki użytkownika Circle, aby działały jako miejsca docelowe upuszczania dla przeciągniętych danych Circle. Zaimplementujesz kod, który umożliwia przeniesienie okręgu z jednego panelu do innego lub utworzenie kopii kontrolki Circle przez przytrzymanie klawisza Ctrl podczas przeciągania i upuszczania okręgu.

  1. Otwórz plik MainWindow.xaml.

  2. Jak pokazano w poniższym kodzie XAML, w każdym z StackPanel kontrolek dodaj programy obsługi dla zdarzeń DragOver i Drop . Nazwij program obsługi zdarzeń , panel_DragOveri nadaj DragOverDrop programowi obsługi panel_Dropzdarzeń nazwę .

    Domyślnie panele nie są miejscami docelowymi. Aby je włączyć, dodaj AllowDrop właściwość do obu paneli i ustaw wartość na 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. Otwórz plik MainWindows.xaml.cs lub MainWindow.xaml.vb.

  4. Dodaj następujący kod dla programu obsługi zdarzeń DragOver .

    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
    

    Ten DragOver program obsługi zdarzeń wykonuje następujące zadania:

    • Sprawdza, czy przeciągane dane zawierają dane "Object", które zostały spakowane w DataObject kontrolce użytkownika Circle i przekazane w wywołaniu metody DoDragDrop.

    • Jeśli dane "Object" są obecne, sprawdza, czy jest naciśnięty klawisz Ctrl .

    • Jeśli naciśnięcie klawisza Ctrl powoduje ustawienie Effects właściwości .Copy W przeciwnym razie ustaw Effects właściwość na Move.

  5. Dodaj następujący kod dla programu obsługi zdarzeń Drop .

    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
    

    Ten Drop program obsługi zdarzeń wykonuje następujące zadania:

    • Sprawdza, czy Drop zdarzenie zostało już obsłużone. Jeśli na przykład okrąg zostanie porzucony w innym okręgu Drop , który obsługuje zdarzenie, nie chcesz, aby panel zawierający koło również go obsłużył.

    • Drop Jeśli zdarzenie nie jest obsługiwane, sprawdza, czy jest naciśnięty klawisz Ctrl.

    • Jeśli naciśnięcie klawisza Ctrl jest wykonywane Drop , tworzy kopię kontrolki Circle i dodaj ją do Children kolekcji StackPanel.

    • Jeśli klawisz Ctrl nie jest naciśnięty, przenosi okrąg z Children kolekcji jej panelu nadrzędnego do Children kolekcji panelu, na który został usunięty.

    • Ustawia właściwość, Effects aby powiadomić metodę DoDragDrop o tym, czy operacja przenoszenia lub kopiowania została wykonana.

  6. Naciśnij klawisz F5, aby skompilować i uruchomić aplikację.

  7. Wybierz tekst green z pliku TextBox.

  8. Przeciągnij tekst nad kontrolką Okrąg i upuść go.

  9. Przeciągnij kontrolkę Okrąg z lewego panelu do prawego panelu i upuść ją. Okrąg jest usuwany z Children kolekcji panelu po lewej stronie i dodawany do kolekcji Podrzędne panelu po prawej stronie.

  10. Przeciągnij kontrolkę Circle z panelu do innego panelu i upuść go, naciskając klawisz Ctrl . Okrąg jest kopiowany, a kopia jest dodawana do Children kolekcji panelu odbierającego.

    Dragging a Circle while pressing the CTRL key

Zobacz też