Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
В этом пошаговом руководстве показано, как создать пользовательский элемент управления, который может участвовать в перетаскивании для передачи данных в Windows Presentation Foundation (WPF).
В этом пошаговом руководстве вы создадите настраиваемую форму WPF UserControl , представляющую фигуру круга. Вы реализуете функциональные возможности элемента управления, чтобы включить передачу данных с помощью перетаскивания. Например, если перетащить один элемент управления Circle в другой, данные цвета заливки копируются из исходного круга в целевой объект. При перетаскивании из элемента управления "Круг" в элемент управления TextBox, строковое представление цвета заливки копируется в элемент управления TextBox. Вы также создадите небольшое приложение, содержащее два элемента управления панелью и TextBox, чтобы проверить функциональность перетаскивания. Вы напишете код, позволяющий панелям обрабатывать удаленные данные Circle, что позволит перемещать или копировать круги из коллекции "Дочерние" одной панели в другую.
В этом пошаговом руководстве рассматриваются следующие задачи:
Создайте пользовательский элемент управления.
Включите пользовательский элемент управления в качестве источника перетаскивания.
Включите пользовательский элемент управления в качестве целевого объекта удаления.
Включите панель для получения данных, удаленных из пользовательского элемента управления.
Предпосылки
Для выполнения этого пошагового руководства вам потребуется Visual Studio.
Создание проекта приложения
В этом разделе вы создадите инфраструктуру приложений, которая включает главную страницу с двумя панелями и a TextBox.
Создайте проект приложения WPF в Visual Basic или Visual C# с именем
DragDropExample. Дополнительные сведения см. в разделе Пошаговое руководство: Мое первое настольное приложение WPF.Откройте файл MainWindow.xaml.
Добавьте следующую разметку между открывающим и закрывающим Grid тегами.
Эта разметка создает пользовательский интерфейс для тестового приложения.
<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>
Добавление нового пользовательского элемента управления в проект
В этом разделе вы добавите в проект новый пользовательский элемент управления.
В меню "Проект" выберите "Добавить элемент управления пользователем".
В диалоговом окне "Добавление нового элемента " измените имя
Circle.xamlи нажмите кнопку "Добавить".Circle.xaml и его связанный код добавлены в проект.
Откройте Circle.xaml.
Этот файл будет содержать элементы интерфейса для пользовательского элемента управления.
Добавьте следующую разметку в корневой элемент Grid, чтобы создать простой пользовательский элемент управления, имеющий синий круг в качестве его интерфейса.
<Ellipse x:Name="circleUI" Height="100" Width="100" Fill="Blue" />Откройте Circle.xaml.cs или Circle.xaml.vb.
В C#добавьте следующий код после конструктора без параметров для создания конструктора копирования. В Visual Basic добавьте следующий код для создания конструктора без параметров и конструктора копирования.
Чтобы разрешить копирование пользовательского элемента управления, добавьте метод конструктора копирования в файл кода программной части. В упрощенном элементе управления "Круг" вы будете копировать только заливку и размер пользовательского элемента управления.
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
Добавление пользовательского элемента управления в главное окно
Откройте файл MainWindow.xaml.
Добавьте следующий КОД XAML в открывающий Window тег, чтобы создать ссылку на пространство имен XML для текущего приложения.
xmlns:local="clr-namespace:DragDropExample"StackPanelСначала добавьте следующий КОД XAML, чтобы создать два экземпляра пользовательского элемента управления Circle на первой панели.
<local:Circle Margin="2" /> <local:Circle Margin="2" />Полный КОД XAML для панели выглядит следующим образом.
<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>
Реализация событий источника перетаскивания в пользовательском элементе управления
В этом разделе вы переопределите OnMouseMove метод и инициируете операцию перетаскивания.
Если начнется перетаскивание (нажата кнопка мыши и осуществляется перемещение), вы упакуете данные, которые будут переданы в объект DataObject. В этом случае элемент управления Circle упаковит три элемента данных; строковое представление цвета заливки, двойное представление его высоты и копия самого себя.
Запуск операции перетаскивания
Откройте Circle.xaml.cs или Circle.xaml.vb.
Добавьте следующее OnMouseMove переопределение для обработки класса для события 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Это OnMouseMove переопределение выполняет следующие задачи:
Проверяет, нажимается ли левая кнопка мыши во время перемещения мыши.
Упаковывает данные объекта Circle в DataObject. В этом случае элемент управления Circle упаковыт три элемента данных; строковое представление цвета заливки, двойное представление его высоты и копия самого себя.
Вызывает статический DragDrop.DoDragDrop метод для запуска операции перетаскивания. В метод передаются DoDragDrop следующие три параметра:
dragSource— ссылка на этот элемент управления.data— объект DataObject, созданный в предыдущем коде.allowedEffects— разрешенные операции перетаскивания, которые являются Copy или Move.
Нажмите клавишу F5, чтобы создать и запустить приложение.
Щелкните один из элементов управления "Круг" и перетащите его по панелям, другому кругу и элементу TextBox. При перетаскивании поверх TextBox курсор изменяется, чтобы указать перемещение.
Перетаскивая круг поверх TextBox, нажмите клавишу Ctrl. Обратите внимание на изменение курсора для указания копии.
Перетащите круг на TextBox. Строковое представление цвета заливки круга добавляется к представлению TextBox.
По умолчанию курсор изменится во время операции перетаскивания, чтобы указать, какой эффект будет иметь удаление данных. Вы можете изменить обратную связь для пользователя, обрабатывая событие GiveFeedback и задав другой курсор.
Предоставление отзывов пользователю
Откройте Circle.xaml.cs или Circle.xaml.vb.
Добавьте следующее OnGiveFeedback переопределение для обработки класса для события 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Это OnGiveFeedback переопределение выполняет следующие задачи:
Нажмите клавишу F5, чтобы создать и запустить приложение.
Перетащите один из элементов управления Circle поверх панелей, другого круга и элемента TextBox. Обратите внимание, что курсоры теперь являются пользовательскими курсорами, указанными в OnGiveFeedback переопределении.
Выделите текст
greenиз элемента TextBox.Перетащите текст в
greenэлемент управления Circle. Обратите внимание, что курсоры по умолчанию отображаются для указания эффектов операции перетаскивания. Курсор обратной связи всегда устанавливается источником перетаскивания.
Реализовать события назначения перетаскивания в элементе управления пользователя
В этом разделе вы укажете, что пользовательский элемент управления является целевым объектом удаления, переопределите методы, позволяющие пользовательскому элементу управления быть целевым объектом удаления, и обрабатывать данные, которые удаляются на нем.
Включение пользовательского элемента управления в качестве целевого объекта удаления
Откройте Circle.xaml.
В открываемом UserControl теге добавьте AllowDrop свойство и задайте для него значение
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">
Метод OnDrop вызывается, когда для свойства AllowDrop задано значение true, а данные из источника перетаскивания сбрасываются на элемент пользовательского управления "Круг". В этом методе вы обработаете данные, которые были исключены, и примените их к Circle.
Обработка отвергнутых данных
Откройте Circle.xaml.cs или Circle.xaml.vb.
Добавьте следующее OnDrop переопределение для обработки класса для события 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Это OnDrop переопределение выполняет следующие задачи:
GetDataPresent Использует метод для проверки, содержит ли перетаскиваемые данные строковый объект.
GetData Использует метод извлечения строковых данных, если они присутствуют.
BrushConverter используется, чтобы попытаться преобразовать строку в Brush.
Если преобразование выполнено успешно, применяет кисть к FillEllipse пользовательскому интерфейсу элемента управления Circle.
Помечает событие Drop как обработанное. Вы должны пометить событие удаления как обработанное, чтобы другие элементы, получающие это событие, знали, что элемент управления "Круг" обработал его.
Нажмите клавишу F5, чтобы создать и запустить приложение.
Выделите текст
greenв элементе TextBox.Перетащите текст в элемент управления Circle и удалите его. Круг изменяется с синего на зеленый.
Введите текст
greenв поле TextBox.Выделите текст
greв элементе TextBox.Перетащите его в элемент управления Circle и удалите его. Обратите внимание, что курсор изменяется, чтобы указать, что перетаскивание разрешено, но цвет круга не изменяется, так как
greне является допустимым цветом.Перетащите элемент управления "Зеленый круг" и перетащите элемент управления "Синий круг". Круг изменяется с синего на зеленый. Обратите внимание, что отображаемый курсор зависит от того, является ли TextBox или Circle источником перетаскивания.
AllowDrop Задание свойства true и обработка удаленных данных — это все, что необходимо для включения элемента в целевой объект удаления. Однако для улучшения взаимодействия с пользователем следует также обрабатывать события DragEnter, DragLeave и DragOver. В этих событиях можно выполнять проверки и предоставлять пользователю дополнительные отзывы перед удалением данных.
Если данные перетаскиваются по элементу управления "Круг", элемент управления должен уведомить источник перетаскивания о том, может ли он обрабатывать данные, перетаскиваемые. Если элемент управления не знает, как обрабатывать данные, он должен отказаться от удаления. Для этого необходимо обработать DragOver событие и задать Effects свойство.
Чтобы убедиться, что удаление данных разрешено
Откройте Circle.xaml.cs или Circle.xaml.vb.
Добавьте следующее OnDragOver переопределение для обработки класса для события 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Это OnDragOver переопределение выполняет следующие задачи:
Нажмите клавишу F5, чтобы создать и запустить приложение.
Выделите текст
greв элементе TextBox.Перетащите текст в элемент управления Circle. Обратите внимание, что курсор теперь изменяется, чтобы указать, что удаление не допускается, так как
greне является допустимым цветом.
Вы можете дополнительно улучшить взаимодействие с пользователем, применяя предварительную версию операции удаления. Для пользовательского элемента управления Circle вы переопределите методы OnDragEnter и OnDragLeave. Когда данные перетаскиваются по элементу управления, текущий фон Fill сохраняется во временной переменной. Затем строка преобразуется в кисть и применяется к Ellipse пользовательскому интерфейсу Circle. Если данные перетаскиваются из круга, но не сбрасываются, исходное Fill значение повторно применяется к Кругу.
Предварительный просмотр эффектов перетаскивания и отпускания
Откройте Circle.xaml.cs или Circle.xaml.vb.
В классе Circle объявите приватную Brush переменную с именем
_previousFillи инициализируйте ееnull.public partial class Circle : UserControl { private Brush _previousFill = null;Public Class Circle Private _previousFill As Brush = NothingДобавьте следующее OnDragEnter переопределение для обработки класса для события 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Это OnDragEnter переопределение выполняет следующие задачи:
Добавьте следующее OnDragLeave переопределение для обработки класса для события 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Это OnDragLeave переопределение выполняет следующие задачи:
Нажмите клавишу F5, чтобы создать и запустить приложение.
Выделите текст
greenв элементе TextBox.Перетащите текст на элемент управления кругом, не отпуская его. Круг изменяется с синего на зеленый.
Перетащите текст из элемента управления Circle. Круг изменяется с зеленого на синий.
Включение панели для получения перетаскиваемых данных
В этом разделе описано, как включить панели, на которых размещаются элементы управления Circle, в качестве целевых объектов удаления для перетаскиваемых данных Circle. Вы реализуете код, позволяющий перемещать круг с одной панели на другую или создавать копию контроля "Круг", удерживая клавишу Ctrl при перетаскивании и отпускании круга.
Откройте файл MainWindow.xaml.
Как показано в следующем XAML, в каждом из StackPanel элементов управления добавьте обработчики для событий DragOver и Drop. Назовите обработчик событий DragOver как
panel_DragOver, и назовите обработчик событий Drop какpanel_Drop.По умолчанию панели не являются целевыми объектами удаления. Чтобы включить их, добавьте AllowDrop свойство на обе панели и задайте значение
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>Откройте MainWindows.xaml.cs или MainWindow.xaml.vb.
Добавьте следующий код для обработчика 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Этот DragOver обработчик событий выполняет следующие задачи:
Проверяет, содержит ли перетаскиваемые данные данные object, которые были упаковированы в DataObject элемент управления "Круг" и переданы в вызов DoDragDrop.
Если данные "Object" присутствуют, проверяется, нажата ли клавиша CTRL.
Если клавиша Ctrl нажата, задает свойству Effects значение Copy. В противном случае задайте значение свойства Effects на Move.
Добавьте следующий код для обработчика 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Этот Drop обработчик событий выполняет следующие задачи:
Проверяет, было ли событие Drop уже обработано. Например, если круг размещается на другом круге, обрабатывающем событие Drop, не требуется, чтобы панель, содержащая круг, также его обрабатывала.
Drop Если событие не обрабатывается, проверяет, нажимается ли клавиша CTRL.
Если клавиша Ctrl нажата, когда происходит Drop, создается копия элемента управления Circle и добавляется в Children коллекцию StackPanel.
Если клавиша CTRL не нажата, круг перемещается из Children коллекции родительской панели в Children коллекцию панели, на которую он был перемещён.
Задает свойство Effects, чтобы метод DoDragDrop мог определить, была ли выполнена операция перемещения или копирования.
Нажмите клавишу F5, чтобы создать и запустить приложение.
Выделите текст
greenиз элемента TextBox.Перетащите текст по элементу управления Circle и удалите его.
Перетащите элемент управления Circle с левой панели на правую панель и удалите его. Круг удаляется из Children коллекции левой панели и добавляется в коллекцию Дочерних элементов правой панели.
Перетащите элемент управления "Круг" из панели в другую панель и удалите его при нажатии клавиши CTRL . Круг копируется, а копия добавляется в Children коллекцию принимающей панели.
См. также
.NET Desktop feedback