Visão geral de arrastar e soltar
Este tópico fornece uma visão geral do suporte a arrastar e soltar em aplicativos do Windows Presentation Foundation (WPF). Arrastar e soltar geralmente se refere a um método de transferência de dados que envolve o uso de um mouse (ou algum outro dispositivo apontador) para selecionar um ou mais objetos, arrastar esses objetos sobre algum destino de soltar desejado na interface do usuário (UI) e soltá-los.
Suporte a arrastar e soltar no WPF
As operações de arrastar e soltar normalmente envolvem duas partes: uma fonte de arrasto da qual o objeto arrastado se origina e um destino de soltar que recebe o objeto solto. A origem do arrastar e o destino do soltar podem ser elementos da interface de utilizador na mesma aplicação ou em uma aplicação diferente.
O tipo e o número de objetos que podem ser manipulados com o recurso de arrastar e soltar são completamente arbitrários. Por exemplo, arquivos, pastas e seleções de conteúdo são alguns dos objetos mais comuns manipulados por meio de operações de arrastar e soltar.
As ações específicas executadas durante uma operação de arrastar e soltar são específicas do aplicativo e, muitas vezes, determinadas pelo contexto. Por exemplo, arrastar uma seleção de arquivos de uma pasta para outra no mesmo dispositivo de armazenamento move os arquivos por padrão, enquanto arrastar arquivos de um compartilhamento UNC (Convenção de Nomenclatura Universal) para uma pasta local copia os arquivos por padrão.
Os recursos de arrastar e soltar fornecidos pelo WPF são projetados para serem altamente flexíveis e personalizáveis para suportar uma ampla variedade de cenários de arrastar e soltar. Arrastar e soltar suporta a manipulação de objetos dentro de um único aplicativo ou entre aplicativos diferentes. Arrastar e soltar entre aplicativos WPF e outros aplicativos do Windows também é totalmente suportado.
No WPF, qualquer UIElement ou ContentElement pode participar na funcionalidade de arrastar e soltar. Os eventos e métodos necessários para operações de arrastar e soltar são definidos na classe DragDrop. As classes UIElement e ContentElement contêm aliases para os eventos DragDrop anexados para que os eventos apareçam na lista de membros da classe quando um UIElement ou ContentElement é herdado como um elemento base. Os manipuladores de eventos anexados a esses eventos estão ligados ao evento anexado subjacente DragDrop e recebem a mesma instância dos dados do evento. Para obter mais informações, consulte o evento UIElement.Drop.
Importante
OLE arrastar e soltar não funciona enquanto estiver na zona da Internet.
Transferência de Dados
Arrastar e soltar faz parte da área mais geral de transferência de dados. A transferência de dados inclui operações de arrastar e soltar e copiar e colar. Uma operação de arrastar e soltar é análoga a uma operação de copiar e colar ou cortar e colar que é usada para transferir dados de um objeto ou aplicativo para outro usando a área de transferência do sistema. Ambos os tipos de operações exigem:
Um objeto de origem que fornece os dados.
Uma forma de armazenar temporariamente os dados transferidos.
Um objeto de destino que recebe os dados.
Em uma operação de copiar e colar, a área de transferência do sistema é usada para armazenar temporariamente os dados transferidos; Em uma operação de arrastar e soltar, um DataObject é usado para armazenar os dados. Conceitualmente, um objeto de dados consiste em um ou mais pares de um Object que contém os dados reais e um identificador de formato de dados correspondente.
A fonte de arrasto inicia uma operação de arrastar e soltar chamando o método DragDrop.DoDragDrop estático e passando-lhe os dados transferidos. O método DoDragDrop encapsulará automaticamente os dados em um DataObject se necessário. Para obter maior controle sobre o formato de dados, você pode encapsular os dados em um DataObject antes de passá-los para o método DoDragDrop. O alvo de queda é responsável por extrair os dados do DataObject. Para obter mais informações sobre como trabalhar com objetos de dados, consulte Data and Data Objects.
A origem e o destino de uma operação de arrastar e soltar são elementos da interface do usuário; no entanto, os dados que estão realmente sendo transferidos normalmente não têm uma representação visual. Você pode escrever código para fornecer uma representação visual dos dados que são arrastados, como ocorre ao arrastar arquivos no Windows Explorer. Por padrão, o feedback é fornecido ao usuário alterando o cursor para representar o efeito que a operação de arrastar e soltar terá sobre os dados, como se os dados serão movidos ou copiados.
Efeitos de arrastar e soltar
As operações de arrastar e soltar podem ter efeitos diferentes nos dados transferidos. Por exemplo, você pode copiar os dados ou movê-los. O WPF define uma enumeração DragDropEffects que você pode usar para especificar o efeito de uma operação de arrastar e soltar. Na fonte de arrasto, você pode especificar os efeitos que a fonte permitirá no método DoDragDrop. No destino drop, você pode especificar o efeito que o destino pretende na propriedade Effects da classe DragEventArgs. Quando o destino de soltar especifica o seu efeito pretendido no evento DragOver, essa informação é passada de volta à origem do arrasto no evento GiveFeedback. A fonte de arrasto usa estas informações para informar o utilizador sobre o efeito que o alvo de depósito intenciona ter sobre os dados. Quando os dados são descartados, o alvo de descarte especifica o seu efeito real no evento Drop. Essas informações são passadas de volta para a fonte de arrasto como o valor de retorno do método DoDragDrop. Se o destino de soltar retornar um efeito que não está na lista de fontes de arraste do allowedEffects
, a operação de arrastar e soltar será cancelada sem que ocorra qualquer transferência de dados.
É importante lembrar que, no WPF, os valores de DragDropEffects são usados apenas para fornecer comunicação entre a fonte de arrasto e o destino de soltar em relação aos efeitos da operação de arrastar e soltar. O efeito real da operação de arrastar e soltar depende de você escrever o código apropriado em seu aplicativo.
Por exemplo, o destino de descarte pode especificar que o efeito de soltar dados nele é mover os dados. No entanto, para mover os dados, eles devem ser adicionados ao elemento de destino e removidos do elemento de origem. O elemento source pode indicar que ele permite mover os dados, mas se você não fornecer o código para remover os dados do elemento source, o resultado final será que os dados são copiados e não movidos.
Eventos de arrastar e soltar
As operações de arrastar e soltar suportam um modelo controlado por eventos. Tanto a fonte de arrasto quanto o alvo de soltura usam um conjunto padrão de eventos para executar operações de arrasto e soltura. As tabelas a seguir resumem os eventos padrão de arrastar e soltar. Estes são eventos anexados na classe DragDrop. Para obter mais informações sobre eventos anexados, consulte Visão geral de eventos anexados.
Arrastar eventos de origem
Evento | Resumo |
---|---|
GiveFeedback | Esse evento ocorre continuamente durante uma operação de arrastar e soltar e permite que a fonte de soltar forneça informações de feedback ao usuário. Esse feedback geralmente é dado alterando a aparência do ponteiro do mouse para indicar os efeitos permitidos pelo alvo de queda. Este é um evento borbulhante. |
QueryContinueDrag | Este evento ocorre quando há uma alteração nos estados das teclas ou dos botões do mouse durante uma operação de arrastar e soltar, permitindo que a origem de soltura cancele essa operação com base nos estados das teclas/botões. Este é um evento borbulhante. |
PreviewGiveFeedback | Versão de tunelamento do GiveFeedback. |
PreviewQueryContinueDrag | Versão de tunelamento do QueryContinueDrag. |
Soltar eventos de destino
Evento | Resumo |
---|---|
DragEnter | Este evento ocorre quando um objeto é arrastado para a fronteira da zona de soltura. Este é um evento borbulhante. |
DragLeave | Este evento ocorre quando um objeto é arrastado para fora do limite da área de queda. Este é um evento borbulhante. |
DragOver | Este evento ocorre continuamente enquanto um objeto é arrastado (movido) dentro dos limites do alvo de soltura. Este é um evento vibrante. |
Drop | Este evento ocorre quando um objeto é solto no ponto de largada. Este é um evento borbulhante. |
PreviewDragEnter | Versão de tunelamento do DragEnter. |
PreviewDragLeave | Versão de tunelamento do DragLeave. |
PreviewDragOver | Versão de tunelamento do DragOver. |
PreviewDrop | Versão de tunelamento do Drop. |
Para manipular eventos de arrastar e soltar para instâncias de um objeto, adicione manipuladores para os eventos listados nas tabelas anteriores. Para lidar com eventos de arrastar e soltar ao nível da classe, sobreponha os métodos virtuais correspondentes On*Event e On*PreviewEvent. Para obter mais informações, consulte Manipulação de Classes de Eventos Encaminhados por Classes Base de Controle.
Implementando o recurso de arrastar e soltar
Um elemento da interface do usuário pode ser uma fonte de arrasto, um destino de soltar ou ambos. Para implementar o recurso básico de arrastar e soltar, você escreve código para iniciar a operação de arrastar e soltar e processar os dados soltos. Você pode aprimorar a experiência de arrastar e soltar manipulando eventos opcionais de arrastar e soltar.
Para implementar o recurso básico de arrastar e soltar, você concluirá as seguintes tarefas:
Identifique o elemento que será uma fonte de arrasto. Uma fonte de arrasto pode ser um UIElement ou um ContentElement.
Crie um manipulador de eventos na fonte de arraste que iniciará a operação de arrastar e soltar. O evento é tipicamente o evento MouseMove.
No manipulador de eventos drag source, chame o método DoDragDrop para iniciar a operação de arrastar e soltar. Na chamada DoDragDrop, especifique a fonte de arrasto, os dados a serem transferidos e os efeitos permitidos.
Identifique o elemento que será um destino de soltar. Um alvo de queda pode ser UIElement ou um ContentElement.
No alvo de arraste, defina a propriedade AllowDrop como
true
.No destino drop, crie um manipulador de eventos Drop para processar os dados descartados.
No manipulador de eventos Drop, extraia os dados do DragEventArgs usando os métodos GetDataPresent e GetData.
No manipulador de eventos Drop, use os dados para executar a operação de arrastar e soltar desejada.
Você pode melhorar a sua implementação de arrastar e soltar ao criar um DataObject personalizado e manipular eventos opcionais relacionados à origem de arrastar e alvo de soltar, conforme demonstrado nas tarefas seguintes:
Para transferir dados personalizados ou vários itens de dados, crie um DataObject para passar para o método DoDragDrop.
Para executar ações adicionais durante um arrasto, deve-se manipular os eventos DragEnter, DragOvere DragLeave no alvo de soltar.
Para alterar a aparência do ponteiro do mouse, manipule o evento GiveFeedback na fonte de arraste.
Para alterar como a operação de arrastar e soltar é cancelada, manipule o evento QueryContinueDrag na fonte de arrasto.
Exemplo de arrastar e soltar
Esta seção descreve como implementar o recurso de arrastar e soltar para um elemento Ellipse. O Ellipse é tanto uma fonte de arrasto como um destino de largada. Os dados transferidos são a representação de cadeia de caracteres da propriedade Fill da elipse. O XAML a seguir mostra o elemento Ellipse e os eventos relacionados a arrastar e soltar que ele manipula. Para obter etapas completas sobre como implementar o recurso de arrastar e soltar, consulte Passo a passo: Habilitando arrastar e soltar em um controle de usuário.
<Ellipse Height="50" Width="50" Fill="Green"
MouseMove="ellipse_MouseMove"
GiveFeedback="ellipse_GiveFeedback"
AllowDrop="True"
DragEnter="ellipse_DragEnter" DragLeave="ellipse_DragLeave"
DragOver="ellipse_DragOver" Drop="ellipse_Drop" />
Habilitando um elemento para ser uma fonte de arraste
Um objeto que é uma fonte de arrasto é responsável por:
Identificar quando ocorre um arrasto.
Iniciando a operação de arrastar e soltar.
Identificação dos dados a transferir.
Especificando os efeitos que a operação de arrastar e soltar pode ter nos dados transferidos.
A fonte de arrastar também pode dar feedback ao usuário sobre as ações permitidas (mover, copiar, nenhuma) e pode cancelar a operação de arrastar e soltar com base na entrada adicional do usuário, como pressionar a tecla ESC durante o arrasto.
É responsabilidade do seu aplicativo determinar quando ocorre um arrasto e, em seguida, iniciar a operação de arrastar e soltar chamando o método DoDragDrop. Normalmente, isso ocorre quando um evento MouseMove ocorre sobre o elemento a ser arrastado enquanto um botão do mouse é pressionado. O exemplo a seguir mostra como iniciar uma operação de arrastar e soltar a partir do manipulador de eventos MouseMove de um elemento Ellipse para torná-lo uma fonte de arrasto. Os dados transferidos são a representação de cadeia de caracteres da propriedade Fill da elipse.
private void ellipse_MouseMove(object sender, MouseEventArgs e)
{
Ellipse ellipse = sender as Ellipse;
if (ellipse != null && e.LeftButton == MouseButtonState.Pressed)
{
DragDrop.DoDragDrop( ellipse,
ellipse.Fill.ToString(),
DragDropEffects.Copy);
}
}
Private Sub Ellipse_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Input.MouseEventArgs)
Dim ellipse = TryCast(sender, Ellipse)
If ellipse IsNot Nothing AndAlso e.LeftButton = MouseButtonState.Pressed Then
DragDrop.DoDragDrop(ellipse, ellipse.Fill.ToString(), DragDropEffects.Copy)
End If
End Sub
Dentro do manipulador de eventos MouseMove, chame o método DoDragDrop para iniciar a operação de arrastar e soltar. O método DoDragDrop usa três parâmetros:
dragSource
– Uma referência ao objeto de dependência que é a fonte dos dados transferidos; Normalmente, esta é a origem do evento MouseMove.data
- Um objeto que contém os dados transferidos, encapsulados em um DataObject.allowedEffects
- Um dos DragDropEffects valores de enumeração que especifica os efeitos permitidos da operação de arrastar e soltar.
Qualquer objeto serializável pode ser passado no parâmetro data
. Se os dados ainda não estiverem encapsulados em um DataObject, eles serão automaticamente encapsulados em um novo DataObject. Para passar vários itens de dados, você deve criar o DataObject você mesmo e passá-lo para o método DoDragDrop. Para obter mais informações, consulte Data and Data Objects.
O parâmetro allowedEffects
é usado para especificar o que a origem de arraste permitirá que o alvo de largar faça com os dados transferidos. Os valores comuns para uma fonte de arrasto são Copy, Movee All.
Observação
O destino de queda também é capaz de especificar quais efeitos pretende em resposta aos dados descartados. Por exemplo, se o destino de descarte não reconhecer o tipo de dados a ser descartado, ele poderá recusar os dados definindo seus efeitos permitidos como None. Ele normalmente faz isso em seu manipulador de eventos DragOver.
Uma fonte de arrasto pode, opcionalmente, manipular os eventos GiveFeedback e QueryContinueDrag. Esses eventos têm manipuladores padrão que são usados, a menos que você marque os eventos como manipulados. Normalmente, você ignorará esses eventos, a menos que tenha uma necessidade específica de alterar seu comportamento padrão.
O evento GiveFeedback é gerado continuamente enquanto a fonte de arrasto está sendo arrastada. O manipulador padrão para esse evento verifica se a origem de arrasto está sobre um destino de soltar válido. Se for, ele verifica os efeitos permitidos do alvo de queda. Em seguida, fornece feedback ao utilizador final sobre os efeitos de arrasto permitidos. Isso geralmente é feito alterando o cursor do mouse para um cursor de não-soltar, copiar ou mover. Você só deve manipular esse evento se precisar usar cursores personalizados para fornecer comentários ao usuário. Se processar este evento, certifique-se de marcá-lo como processado para que o gestor padrão não substitua o seu gestor.
O evento QueryContinueDrag é gerado continuamente enquanto a fonte de arrasto está sendo arrastada. Você pode manipular esse evento para determinar qual ação termina a operação de arrastar e soltar com base no estado das teclas ESC, SHIFT, CTRL e ALT, bem como no estado dos botões do mouse. O manipulador padrão para esse evento cancela a operação de arrastar e soltar se a tecla ESC for pressionada e solta os dados se o botão do mouse for liberado.
Atenção
Esses eventos são gerados continuamente durante a operação de arrastar e soltar. Portanto, você deve evitar tarefas que consomem muitos recursos nos manipuladores de eventos. Por exemplo, use um cursor armazenado em cache em vez de criar um novo cursor cada vez que o evento GiveFeedback for gerado.
Habilitando um elemento para ser um destino de descarte
Um objeto que é um destino de descarte é responsável por:
Especificando que é um destino de descarte válido.
Responder à fonte de arrasto quando ela arrasta sobre o destino.
Verificar se os dados transferidos estão em um formato que ele pode receber.
Processamento dos dados descartados.
Para especificar que um elemento é um destino drop, defina sua propriedade AllowDrop como true
. Os eventos drop target serão então gerados no elemento para que você possa manipulá-los. Durante uma operação de arrastar e soltar, a seguinte sequência de eventos ocorre no alvo de soltar:
O evento DragEnter ocorre quando os dados são arrastados para o limite do destino de soltura. Normalmente, você manipula esse evento para fornecer uma visualização dos efeitos da operação de arrastar e soltar, se apropriado para seu aplicativo. Não defina a propriedade DragEventArgs.Effects no evento DragEnter, pois ela será substituída no evento DragOver.
O exemplo a seguir mostra o manipulador de eventos DragEnter para um elemento Ellipse. Este código antecipa os efeitos da operação de arrastar e soltar guardando o pincel Fill atual. Em seguida, ele usa o método GetDataPresent para verificar se o DataObject que está sendo arrastado sobre a elipse contém dados de cadeia de caracteres que podem ser convertidos em um Brush. Em caso afirmativo, os dados são extraídos usando o método GetData. Em seguida, é convertido em Brush e aplicado à elipse. A alteração é revertida no manipulador de eventos DragLeave. Se os dados não puderem ser convertidos em um Brush, nenhuma ação será executada.
private Brush _previousFill = null;
private void ellipse_DragEnter(object sender, DragEventArgs e)
{
Ellipse ellipse = sender as Ellipse;
if (ellipse != null)
{
// Save the current Fill brush so that you can revert back to this value in DragLeave.
_previousFill = ellipse.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);
ellipse.Fill = newFill;
}
}
}
}
Private _previousFill As Brush = Nothing
Private Sub Ellipse_DragEnter(ByVal sender As System.Object, ByVal e As System.Windows.DragEventArgs)
Dim ellipse = TryCast(sender, Ellipse)
If ellipse IsNot Nothing Then
' Save the current Fill brush so that you can revert back to this value in DragLeave.
_previousFill = ellipse.Fill
' If the DataObject contains string data, extract it.
If e.Data.GetDataPresent(DataFormats.StringFormat) Then
Dim dataString = 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 = CType(converter.ConvertFromString(dataString), Brush)
ellipse.Fill = newFill
End If
End If
End If
End Sub
O evento DragOver ocorre continuamente enquanto os dados são arrastados sobre o destino de soltar. Esse evento é emparelhado com o evento GiveFeedback na fonte de arrasto. No manipulador de eventos DragOver, você normalmente usa os métodos GetDataPresent e GetData para verificar se os dados transferidos estão em um formato que o destino de descarte pode processar. Você também pode verificar se alguma tecla modificadora é pressionada, o que normalmente indicará se o usuário pretende mover ou copiar uma ação. Depois que essas verificações forem executadas, você define a propriedade DragEventArgs.Effects para notificar a fonte de arrasto sobre o efeito que a eliminação dos dados terá. A fonte de arraste recebe essas informações no evento GiveFeedback args e pode definir um cursor apropriado para dar feedback ao usuário.
O exemplo a seguir mostra o manipulador de eventos DragOver para um elemento Ellipse. Esse código verifica se o DataObject que está sendo arrastado sobre a elipse contém dados de cadeia de caracteres que podem ser convertidos em um Brush. Em caso afirmativo, ele define a propriedade DragEventArgs.Effects como Copy. Isso indica à fonte de arraste que os dados podem ser copiados para a elipse. Se os dados não puderem ser convertidos em um Brush, a propriedade DragEventArgs.Effects será definida como None. Isso indica à fonte de arrasto que a elipse não é um alvo de queda válido para os dados.
private void ellipse_DragOver(object sender, DragEventArgs 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.
BrushConverter converter = new BrushConverter();
if (converter.IsValid(dataString))
{
e.Effects = DragDropEffects.Copy | DragDropEffects.Move;
}
}
}
Private Sub Ellipse_DragOver(ByVal sender As System.Object, ByVal e As System.Windows.DragEventArgs)
e.Effects = DragDropEffects.None
' If the DataObject contains string data, extract it.
If e.Data.GetDataPresent(DataFormats.StringFormat) Then
Dim dataString = 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
e.Effects = DragDropEffects.Copy Or DragDropEffects.Move
End If
End If
End Sub
O evento DragLeave ocorre quando os dados são arrastados para fora da área de destino sem serem soltos. Você manipula esse evento para desfazer qualquer coisa que você fez no manipulador de eventos DragEnter.
O exemplo a seguir mostra o manipulador de eventos DragLeave para um elemento Ellipse. Este código desfaz a visualização executada no manipulador de eventos DragEnter, aplicando o Brush salvo à elipse.
private void ellipse_DragLeave(object sender, DragEventArgs e)
{
Ellipse ellipse = sender as Ellipse;
if (ellipse != null)
{
ellipse.Fill = _previousFill;
}
}
Private Sub Ellipse_DragLeave(ByVal sender As System.Object, ByVal e As System.Windows.DragEventArgs)
Dim ellipse = TryCast(sender, Ellipse)
If ellipse IsNot Nothing Then
ellipse.Fill = _previousFill
End If
End Sub
O evento Drop ocorre quando os dados são descartados sobre o alvo de soltura; por padrão, isso acontece quando o botão do mouse é liberado. No manipulador de eventos Drop, você usa o método GetData para extrair os dados transferidos do DataObject e executar qualquer processamento de dados que seu aplicativo exija. O evento Drop encerra a operação de arrastar e soltar.
O exemplo a seguir mostra o manipulador de eventos Drop para um elemento Ellipse. Esse código aplica os efeitos da operação de arrastar e soltar e é semelhante ao código no manipulador de eventos DragEnter. Ele verifica se o DataObject que está sendo arrastado sobre a elipse contém dados de cadeia de caracteres que podem ser convertidos em um Brush. Em caso afirmativo, o Brush é aplicado à elipse. Se os dados não puderem ser convertidos em um Brush, nenhuma ação será executada.
private void ellipse_Drop(object sender, DragEventArgs e)
{
Ellipse ellipse = sender as Ellipse;
if (ellipse != null)
{
// 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);
ellipse.Fill = newFill;
}
}
}
}
Private Sub Ellipse_Drop(ByVal sender As System.Object, ByVal e As System.Windows.DragEventArgs)
Dim ellipse = TryCast(sender, Ellipse)
If ellipse IsNot Nothing Then
' If the DataObject contains string data, extract it.
If e.Data.GetDataPresent(DataFormats.StringFormat) Then
Dim dataString = 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 = CType(converter.ConvertFromString(dataString), Brush)
ellipse.Fill = newFill
End If
End If
End If
End Sub
Ver também
.NET Desktop feedback