Passo a passo: Ativando o recurso de arrastar e soltar em um controle de usuário
Este passo a passo demonstra como criar um controle de usuário personalizado que pode participar da transferência de dados de arrastar e soltar no Windows Presentation Foundation (WPF).
Neste passo a passo, você criará um UserControl WPF personalizado que representa uma forma de círculo. Você implementará a funcionalidade no controle para habilitar a transferência de dados através do recurso de arrastar e soltar. Por exemplo, se você arrastar de um controle Circle para outro, os dados de cor Fill serão copiados do Circle de origem para o destino. Se você arrastar de um controle Circle para um TextBox, a representação da cadeia de caracteres da cor Fill será copiada para o TextBox. Você também criará um pequeno aplicativo que contém dois controles de painel e um TextBox para testar a funcionalidade de arrastar e soltar. Você escreverá um código que permite que os painéis processem dados de Círculo descartados, o que permitirá mover ou copiar Círculos da coleção Children de um painel para o outro.
Este passo a passo ilustra as seguintes tarefas:
Crie um controle de usuário personalizado.
Habilite o controle de usuário para ser uma fonte de arrasto.
Habilite o controle de usuário para ser um destino de queda.
Habilite um painel para receber dados descartados do controle de usuário.
Pré-requisitos
Você precisa do Visual Studio para concluir este passo a passo.
Criar o projeto de aplicativo
Nesta seção, você criará a infraestrutura do aplicativo, que inclui uma página principal com dois painéis e um TextBox.
Crie um novo projeto de aplicativo WPF em Visual Basic ou Visual C# chamado
DragDropExample
. Para obter mais informações, consulte Passo a passo: Meu primeiro aplicativo de desktop WPF.Abra MainWindow.xaml.
Adicione a seguinte marcação entre as tags Grid de abertura e fechamento.
Essa marcação cria a interface do usuário para o aplicativo de teste.
<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>
Adicionar um novo controle de usuário ao projeto
Nesta seção, você adicionará um novo controle de usuário ao projeto.
No menu Projeto, selecione Adicionar Controle de Usuário.
Na caixa de diálogo Adicionar Novo Item, altere o nome para
Circle.xaml
e clique em Adicionar.Circle.xaml e o seu código subjacente são adicionados ao projeto.
Abrir o ficheiro Circle.xaml.
Este ficheiro conterá os elementos da interface de utilizador do controlo de utilizador.
Adicione a seguinte marcação à raiz Grid para criar um controlo de utilizador simples que tenha um círculo azul como a sua interface de utilizador.
<Ellipse x:Name="circleUI" Height="100" Width="100" Fill="Blue" />
Abra Circle.xaml.cs ou Circle.xaml.vb.
Em C#, adicione o seguinte código após o construtor sem parâmetros para criar um construtor copy. No Visual Basic, adicione o código a seguir para criar um construtor sem parâmetros e um construtor de cópia.
Para permitir que o controle de usuário seja copiado, você adiciona um método de construtor de cópia no arquivo code-behind. No controle de usuário Circle simplificado, você copiará apenas o Fill e o tamanho do controle de usuário.
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
Adicionar o controle de usuário à janela principal
Abra MainWindow.xaml.
Adicione o seguinte XAML à tag Window de abertura para criar uma referência de namespace XML para a aplicação atual.
xmlns:local="clr-namespace:DragDropExample"
No primeiro StackPanel, adicione o seguinte XAML para criar duas instâncias do controle de usuário Circle no primeiro painel.
<local:Circle Margin="2" /> <local:Circle Margin="2" />
O XAML completo para o painel tem a seguinte aparência.
<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>
Implementar eventos de origem de arraste no controle de usuário
Nesta seção, você substituirá o método OnMouseMove e iniciará a operação de arrastar e soltar.
Se um arrasto for iniciado (um botão do mouse é pressionado e o mouse é movido), você empacotará os dados a serem transferidos para um DataObject. Nesse caso, o controle Circle empacotará três itens de dados; uma representação de cadeia de caracteres de sua cor de preenchimento, uma representação dupla de sua altura e uma cópia de si mesma.
Para iniciar uma operação de arrastar e soltar
Abra Circle.xaml.cs ou Circle.xaml.vb.
Adicione o seguinte override OnMouseMove para fornecer manipulação de classe para o 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
Essa substituição de OnMouseMove executa as seguintes tarefas:
Verifica se o botão esquerdo do mouse é pressionado enquanto o mouse está em movimento.
Empacota os dados do Círculo em DataObject. Neste caso, o controlo Círculo empacota três itens de dados: uma representação em texto da sua cor de preenchimento, uma representação numérica da sua altura e uma cópia de si próprio.
Chama o método DragDrop.DoDragDrop estático para iniciar a operação de arrastar e soltar. Você passa os três parâmetros a seguir para o método DoDragDrop:
dragSource
– Uma referência a este controlo.data
– O DataObject criado no código anterior.allowedEffects
– As operações de arrastar e soltar permitidas, que são Copy ou Move.
Pressione F5 para criar e executar o aplicativo.
Clique em um dos controles Círculo e arraste-o sobre os painéis, o outro Círculo e o TextBox. Ao arrastar sobre o TextBox, o cursor muda para indicar um movimento.
Ao arrastar um círculo sobre o TextBox, pressione a tecla Ctrl. Observe como o cursor muda para indicar uma cópia.
Arraste e solte um círculo no TextBox. A representação da cadeia de caracteres da cor de preenchimento do Círculo é acrescentada ao TextBox.
Por definição padrão, o cursor será alterado durante uma operação de arrastar e soltar para indicar qual efeito a queda dos dados terá. Você pode personalizar o feedback dado ao usuário manipulando o evento GiveFeedback e definindo um cursor diferente.
Dar feedback ao utilizador
Abra Circle.xaml.cs ou Circle.xaml.vb.
Adicione o seguinte override de OnGiveFeedback para fornecer a manipulação de classe para o 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
Esta substituição de OnGiveFeedback executa as seguintes tarefas:
Pressione F5 para criar e executar o aplicativo.
Arraste um dos controles Círculo sobre os painéis, o outro Círculo e o TextBox. Observe que os cursores agora são os cursores personalizados que você especificou na substituição de OnGiveFeedback.
Selecione o texto
green
no TextBox.Arraste o texto
green
para um controlo circular. Observe que os cursores padrão são mostrados para indicar os efeitos da operação de arrastar e soltar. O cursor de feedback é sempre definido pela fonte de arrasto.
Implementar eventos de destino de descarte no controle de usuário
Nesta secção, irá especificar que o controlo de utilizador é um alvo de arrastar e soltar, substituirá os métodos que permitem que o controlo de utilizador seja um alvo de arrastar e soltar, e processará os dados que são arrastados e soltos nele.
Para permitir que o controle de utilizador seja um destino de arrasto
Abra Circle.xaml.
Na tag de abertura UserControl, adicione a propriedade AllowDrop e defina-a como
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">
O método OnDrop é chamado quando a propriedade AllowDrop é definida como true
e os dados da fonte de arrasto são soltos no controle de usuário Circle. Nesse método, você processará os dados que foram descartados e aplicará os dados ao Círculo.
Para processar os dados descartados
Abra Circle.xaml.cs ou Circle.xaml.vb.
Adicione a seguinte substituição de OnDrop para fornecer manipulação de classe para o 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
Esta substituição de OnDrop executa as seguintes tarefas:
Usa o método GetDataPresent para verificar se os dados arrastados contêm um objeto de cadeia de caracteres.
Usa o método GetData para extrair os dados da cadeia de caracteres se eles estiverem presentes.
Usa um BrushConverter para tentar converter a cadeia de caracteres em um Brush.
Se a conversão for bem-sucedida, aplique o pincel ao Fill do Ellipse que fornece a interface de utilizador do controlo Circle.
Marca o evento Drop como manipulado. Você deve marcar o evento drop como manipulado para que outros elementos que recebem esse evento saibam que o controle de usuário Circle o manipulou.
Pressione F5 para criar e executar o aplicativo.
Selecione o texto
green
no TextBox.Arraste o texto para um controle Circle e solte-o. O Círculo muda de azul para verde.
Digite o texto
green
no TextBox.Selecione o texto
gre
no TextBox.Arraste-o para um controle Circle e solte-o. Observe que o cursor muda para indicar que a gota é permitida, mas a cor do Círculo não muda porque
gre
não é uma cor válida.Arraste do controle Circle verde e solte no controle Circle azul. O Círculo muda de azul para verde. Observe que o cursor que é mostrado depende se o TextBox ou o Círculo é a fonte de arrasto.
Para um elemento ser um alvo de soltar, basta definir a propriedade AllowDrop para true
e processar os dados descartados. No entanto, para fornecer uma melhor experiência ao usuário, você também deve lidar com os eventos DragEnter, DragLeavee DragOver. Nestes eventos, pode realizar verificações e fornecer feedback adicional ao utilizador antes que os dados sejam eliminados.
Quando os dados são arrastados sobre o controle de usuário Circle, o controle deve notificar a fonte de arraste se ele pode processar os dados que estão sendo arrastados. Se o controle não souber como processar os dados, ele deve recusar a queda. Para fazer isso, você manipulará o evento DragOver e definirá a propriedade Effects.
Para verificar se a queda de dados é permitida
Abra Circle.xaml.cs ou Circle.xaml.vb.
Adicione a seguinte substituição de OnDragOver para fornecer manipulação de classe para o 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
Essa substituição de OnDragOver executa as seguintes tarefas:
Pressione F5 para criar e executar o aplicativo.
Selecione o texto
gre
no TextBox.Arraste o texto para um controle Circle. Observe que o cursor agora muda para indicar que a gota não é permitida porque
gre
não é uma cor válida.
Você pode melhorar ainda mais a experiência do utilizador aplicando uma pré-visualização da operação de arrastar e soltar. Para o controlo de utilizador Circle, substituirás os métodos OnDragEnter e OnDragLeave. Quando os dados são arrastados sobre o controlo, o plano de fundo atual Fill é salvo em uma variável temporária. A string é então convertida num pincel e aplicada ao Ellipse que fornece a UI do Círculo. Se o dado for arrastado para fora do Círculo sem ser solto, o valor original Fill será novamente aplicado ao Círculo.
Para visualizar os efeitos da operação de arrastar e soltar
Abra Circle.xaml.cs ou Circle.xaml.vb.
Na classe Circle, declare uma variável Brush privada chamada
_previousFill
e inicialize-a paranull
.public partial class Circle : UserControl { private Brush _previousFill = null;
Public Class Circle Private _previousFill As Brush = Nothing
Adicione a seguinte substituição de OnDragEnter para fornecer manipulação de classe para o 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
Essa substituição de OnDragEnter executa as seguintes tarefas:
Adicione a seguinte substituição de OnDragLeave para fornecer manipulação de classe para o 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
Esta substituição de OnDragLeave executa as seguintes tarefas:
Pressione F5 para criar e executar o aplicativo.
Selecione o texto
green
no TextBox.Arraste o texto sobre um controle Circle sem soltá-lo. O Círculo muda de azul para verde.
Arraste o texto para fora do controle Circle. O Círculo muda de verde para azul.
Habilitar um painel para receber dados largados
Nesta seção, você habilita os painéis que hospedam os controles de usuário do Circle para atuarem como destinos de soltar para dados do Circle arrastados. Você implementará um código que permite mover um Círculo de um painel para outro ou fazer uma cópia de um controle Círculo mantendo pressionada a tecla Ctrl
Abra MainWindow.xaml.
Como mostrado no XAML a seguir, em cada um dos controles StackPanel, adicione manipuladores para os eventos DragOver e Drop. Nomeie o manipulador de eventos DragOver,
panel_DragOver
e nomeie o manipulador de eventos Droppanel_Drop
.Por padrão, os painéis não são alvos de descarte. Para habilitá-los, adicione a propriedade AllowDrop a ambos os painéis e defina o valor como
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>
Abra MainWindows.xaml.cs ou MainWindow.xaml.vb.
Adicione o seguinte código para o manipulador de eventos 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
Este manipulador de eventos DragOver executa as seguintes tarefas:
Verifica se os dados arrastados contêm os dados "Objeto" que foram empacotados no DataObject pelo controle de usuário Circle e passados na chamada para DoDragDrop.
Se os dados "Objeto" estiverem presentes, verifique se a tecla Ctrl está pressionada.
Se a tecla Ctrl for pressionada, define a propriedade Effects como Copy. Caso contrário, defina a propriedade Effects como Move.
Adicione o seguinte código para o manipulador de eventos 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
Este manipulador de eventos Drop executa as seguintes tarefas:
Verifica se o evento Drop já foi manipulado. Por exemplo, se um Círculo for solto em outro Círculo que manipula o evento Drop, você não deseja que o painel que contém o Círculo também o manipule.
Se o evento Drop não for manipulado, verifica se a tecla Ctrl está pressionada.
Se a tecla Ctrl for pressionada quando o Drop acontecer, faça uma cópia do controle Circle e adicione-o à coleção Children do StackPanel.
Se a tecla Ctrl não for pressionada, move-se o Círculo da coleção Children do painel pai para a coleção Children do painel para onde foi colocado.
Define a propriedade Effects para notificar o método DoDragDrop se uma operação de movimentação ou cópia foi executada.
Pressione F5 para criar e executar o aplicativo.
Selecione o texto
green
no TextBox.Arraste o texto para um controlo circular e solte-o.
Arraste um controle Circle do painel esquerdo para o painel direito e solte-o. O Círculo é removido da coleção Children do painel esquerdo e adicionado à coleção Children do painel direito.
Arraste um controle Circle do painel em que ele está para o outro painel e solte-o enquanto pressiona a tecla Ctrl. O Círculo é copiado e a cópia é adicionada à coleção Children do painel recetor.
Ver também
.NET Desktop feedback