Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
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 element WPF UserControl, który reprezentuje kształt koła. 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 z kontrolki Circle do TextBox, do TextBoxzostanie skopiowany łańcuch znaków reprezentujący kolor wypełnienia. Utworzysz również małą aplikację zawierającą dwie kontrolki panelu i TextBox, aby przetestować funkcjonalność przeciągania i upuszczania. Napiszesz kod, który umożliwia panelom przetwarzanie upuszczonych danych okręgów, co pozwoli na przenoszenie lub kopiowanie okręgów z kolekcji elementów podrzędnych jednego panelu do drugiego.
W tym przewodniku przedstawiono następujące zadania:
Utwórz niestandardową kontrolkę użytkownika.
Umożliwianie kontrolki użytkownika jako źródła przeciągania.
Umożliw kontrolce użytkownika działanie jako element docelowy upuszczania.
Umożliwia panelowi odbieranie danych przeciągniętych do niego z kontrolki użytkownika.
Warunki wstępne
Aby ukończyć ten przewodnik, potrzebny jest program Visual Studio.
Tworzenie projektu aplikacji
W tej sekcji utworzysz infrastrukturę aplikacji, która zawiera stronę główną z dwoma panelami i elementem TextBox.
Utwórz nowy projekt aplikacji WPF w Visual Basic lub Visual C# o nazwie
DragDropExample
. Aby uzyskać więcej informacji, zobacz Walkthrough: My first WPF desktop application.Otwórz plik MainWindow.xaml.
Dodaj następujący znacznik między znacznikami 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.
W menu Projekt wybierz pozycję Dodaj kontrolę użytkownika.
W oknie dialogowym Dodawanie nowego elementu zmień nazwę na
Circle.xaml
, a następnie kliknij przycisk Dodaj.Plik Circle.xaml i jego powiązany kod są dodane do projektu.
Otwórz plik Circle.xaml.
Ten plik będzie zawierać elementy interfejsu użytkownika kontrolki użytkownika.
Dodaj następujący znacznik do korzenia Grid, aby utworzyć prostą kontrolkę, która ma niebieski okrąg w interfejsie użytkownika.
<Ellipse x:Name="circleUI" Height="100" Width="100" Fill="Blue" />
Otwórz Circle.xaml.cs lub Circle.xaml.vb.
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, należy dodać metodę konstruktora kopiującego w pliku code-behind. 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
Otwórz plik MainWindow.xaml.
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"
W pierwszym StackPaneldodaj 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ąganie zostanie uruchomione (naciśnięcie przycisku myszy i przeniesienie myszy), spakujesz dane, które mają zostać przesłane do DataObject. 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
Otwórz Circle.xaml.cs lub Circle.xaml.vb.
Dodaj następujące OnMouseMove nadpisanie, aby zapewnić obsługę klasy dla zdarzenia 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
To przesłonięcie OnMouseMove wykonuje następujące zadania:
Sprawdza, czy lewy przycisk myszy jest naciśnięty podczas przesuwania myszy.
Pakuje dane okręgu do 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 rozpocząć operację przeciągania i upuszczania. Następujące trzy parametry należy przekazać do metody DoDragDrop:
dragSource
— odwołanie do tej kontrolki.data
— DataObject utworzona w poprzednim kodzie.allowedEffects
— dozwolone operacje przeciągania i upuszczania, które są Copy lub Move.
Naciśnij F5, aby skompilować i uruchomić aplikację.
Kliknij jedną z kontrolek Circle i przeciągnij ją na panele, drugi okrąg i TextBox. Podczas przeciągania nad TextBox, kursor zmienia się, aby wskazać przesunięcie.
Podczas przeciągania koła po TextBox, naciśnij klawisz Ctrl. Zwróć uwagę, że kursor zmienia się, aby wskazać kopię.
Przeciągnij i upuść okrąg na TextBox. Reprezentacja tekstowa koloru wypełnienia Circle jest dołączana do TextBox.
Domyślnie kursor zmieni się podczas operacji przeciągania i upuszczania, aby wskazać, jakie będą skutki upuszczenia danych. Opinie przekazane użytkownikowi można dostosować, obsługując zdarzenie GiveFeedback i ustawiając inny kursor.
Prześlij opinię użytkownikowi
Otwórz Circle.xaml.cs lub Circle.xaml.vb.
Należy dodać następujące przesłonięcie OnGiveFeedback, aby obsłużyć klasę na zdarzenie 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
To nadpisanie OnGiveFeedback wykonuje następujące zadania:
Naciśnij F5, aby skompilować i uruchomić aplikację.
Przeciągnij jedną z kontrolki Circle na panele, drugą kontrolkę Circle oraz TextBox. Zwróć uwagę, że kursory są teraz kursorami niestandardowymi określonymi w OnGiveFeedback przesłonięcia.
Wybierz tekst
green
z TextBox.Przeciągnij tekst
green
do kontrolki Circle. Zwróć uwagę, że domyślne kursory są wyświetlane w celu wskazania efektów operacji przeciągania i upuszczania. Kursor zwrotny jest zawsze ustawiany przez źródło przeciągnięcia.
Implementowanie zdarzeń miejsca docelowego upuszczania w kontrolce użytkownika
W tej sekcji określisz, że element sterujący użytkownika jest miejscem docelowym upuszczania, nadpiszesz metody, które umożliwiają elementowi sterującemu być miejscem docelowym upuszczania, i przetworzysz dane, które są na nim upuszczane.
Aby umożliwić elementowi sterującemu działanie jako cel upuszczania
Otwórz plik Circle.xaml.
W tagu otwierającego UserControl dodaj właściwość AllowDrop i ustaw ją na wartość
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 właściwość AllowDrop jest ustawiona na true
, a dane ze źródła przeciągania są upuszczane na kontrolkę użytkownika Circle. W tej metodzie przetworzysz dane, które zostały porzucone i zastosujesz dane do okręgu.
Aby przetworzyć upuszczone dane
Otwórz Circle.xaml.cs lub Circle.xaml.vb.
Dodaj następujące OnDrop nadpisanie, aby zapewnić obsługę klasy dla zdarzenia 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
To przesłonięcie OnDrop wykonuje następujące zadania:
Używa metody GetDataPresent, aby sprawdzić, czy przeciągane dane zawierają obiekt ciągu.
Używa metody GetData, aby wyodrębnić dane ciągu, jeśli są obecne.
Używa BrushConverter, aby spróbować przekonwertować ciąg na Brush.
Jeśli konwersja zakończy się pomyślnie, zastosuj pędzel do Fill elementu Ellipse, który zapewnia interfejs użytkownika dla kontrolki Circle.
Oznacza zdarzenie Drop jako obsługiwane. Powinieneś oznaczyć zdarzenie upuszczania jako obsłużone, aby inne elementy, które odbierają to zdarzenie, wiedziały, że kontrolka Circle je obsłużyła.
Naciśnij F5, aby skompilować i uruchomić aplikację.
Wybierz tekst
green
w TextBox.Przeciągnij tekst do kontrolki Okrąg i upuść go. Okrąg zmienia się z niebieskiego na zielony.
Wpisz tekst
green
w TextBox.Wybierz tekst
gre
w TextBox.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.Przeciągnij z zielonego przycisku Circle i upuść na niebieski przycisk Circle. Okrąg zmienia się z niebieskiego na zielony. Zwróć uwagę, że to, który kursor jest wyświetlany, zależy od tego, czy TextBox, czy Circle jest źródłem przeciągania.
Ustawienie właściwości AllowDrop na true
i przetwarzanie upuszczonych danych jest wszystkim, co jest wymagane, aby umożliwić elementowi stanie się miejscem docelowym upuszczania. Jednak aby zapewnić lepsze środowisko użytkownika, należy również obsługiwać zdarzenia DragEnter, DragLeavei DragOver. W takich sytuacjach można przeprowadzić sprawdzenia i dostarczyć użytkownikowi dodatkowe informacje zwrotne, 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ć ich przyjęcia. W tym celu obsłużysz zdarzenie DragOver i ustawisz właściwość Effects.
Aby sprawdzić, czy upuszczanie danych jest dozwolone
Otwórz Circle.xaml.cs lub Circle.xaml.vb.
Dodaj następujące nadpisanie OnDragOver, aby umożliwić obsługę klasy dla zdarzenia 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
Ten OnDragOver mechanizm przesłonięcia wykonuje następujące zadania:
Naciśnij F5, aby skompilować i uruchomić aplikację.
Wybierz tekst
gre
w TextBox.Przeciągnij tekst do elementu kontrolnego z kształtem koła. Zwróć uwagę, że kursor zmienia się, wskazując, że upuszczanie jest niedozwolone, ponieważ
gre
nie jest prawidłowym kolorem.
Możesz jeszcze bardziej poprawić doświadczenie użytkownika, stosując podgląd operacji przeciągania. W przypadku kontrolki użytkownika Circle zastąpisz metody OnDragEnter i OnDragLeave. Po przeciągnięciu danych przez kontrolkę bieżące tło Fill jest zapisywane w zmiennej zastępczej. Ciąg jest następnie konwertowany na pędzel i stosowany na Ellipse, stanowiący część interfejsu użytkownika Circle. Jeśli dane są przeciągane z okręgu bez porzucania, oryginalna wartość Fill zostanie ponownie zastosowana do okręgu.
Aby wyświetlić podgląd efektów operacji przeciągania i upuszczania
Otwórz Circle.xaml.cs lub Circle.xaml.vb.
W klasie Circle zadeklaruj prywatną zmienną Brush o nazwie
_previousFill
i zainicjuj ją na wartośćnull
.public partial class Circle : UserControl { private Brush _previousFill = null;
Public Class Circle Private _previousFill As Brush = Nothing
Dodaj następujące OnDragEnter nadpisanie, aby zapewnić obsługę zdarzenia DragEnter przez klasę.
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
Ta przesłona OnDragEnter wykonuje następujące zadania:
Dodaj następujące OnDragLeave nadpisania w celu zapewnienia obsługi klasy dla zdarzenia 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
To zastąpienie OnDragLeave wykonuje następujące zadania:
Naciśnij F5, aby skompilować i uruchomić aplikację.
Wybierz tekst
green
w TextBox.Przeciągnij tekst nad kontrolką Circle bez upuszczania. Okrąg zmienia się z niebieskiego na zielony.
Przeciągnij tekst z dala od kontrolki Circle. Okrąg zmienia się z zielonego z powrotem na niebieski.
Włącz panel do odbierania przeniesionych 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 Ctrl podczas przeciągania i upuszczania okręgu.
Otwórz plik MainWindow.xaml.
Jak pokazano w poniższym kodzie XAML, w każdym z kontrolek StackPanel dodaj programy obsługi dla zdarzeń DragOver i Drop. Nazwij program obsługi zdarzeń DragOver,
panel_DragOver
i nadaj programowi obsługi zdarzeń Drop nazwępanel_Drop
.Domyślnie panele nie są miejscami docelowymi. Aby je włączyć, dodaj właściwość AllowDrop 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>
Otwórz MainWindows.xaml.cs lub MainWindow.xaml.vb.
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
Ta procedura obsługi zdarzeń DragOver wykonuje następujące zadania:
Sprawdza, czy przeciągane dane zawierają dane "Object", które zostały spakowane w DataObject przez kontrolkę użytkownika Circle i przekazane w wywołaniu do DoDragDrop.
Jeśli dane "Object" są obecne, sprawdza, czy klawisz Ctrl oznaczony jako jest wciśnięty.
Jeśli zostanie naciśnięty klawisz Ctrl, ustaw właściwość Effects na Copy. W przeciwnym razie ustaw właściwość Effects na Move.
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
Ta procedura obsługi zdarzeń Drop wykonuje następujące zadania:
Sprawdza, czy zdarzenie Drop zostało już obsłużone. Jeśli na przykład okrąg zostanie porzucony na innym okręgu, który obsługuje zdarzenie Drop, nie chcesz, aby panel zawierający koło również go obsłużył.
Jeśli zdarzenie Drop nie jest obsługiwane, sprawdza, czy klawisz Ctrl jest wciśnięty.
Jeśli klawisz Ctrl jest naciskany, gdy występuje Drop, utwórz kopię kontrolki Circle i dodaj ją do kolekcji Children elementu StackPanel.
Jeśli Ctrl nie jest naciśnięty, przenosi Okrąg z kolekcji Children panelu nadrzędnego do kolekcji Children panelu, na który został przeniesiony.
Ustawia właściwość Effects, aby powiadomić metodę DoDragDrop o tym, czy wykonano operację przenoszenia, czy kopiowania.
Naciśnij F5, aby skompilować i uruchomić aplikację.
Wybierz tekst
green
z TextBox.Przeciągnij tekst nad kontrolką Okrąg i upuść go.
Przeciągnij kontrolkę Okrąg z lewego panelu do prawego panelu i upuść ją. Okrąg jest usuwany z kolekcji Children w panelu po lewej stronie i dodawany do kolekcji Dzieci w panelu po prawej stronie.
Przeciągnij kontrolkę Circle z jednego panelu do drugiego i upuść ją, trzymając wciśnięty klawisz Ctrl. Okrąg jest kopiowany, a kopia jest dodawana do kolekcji Children panelu odbierającego.
Zobacz też
.NET Desktop feedback