Arrastar e soltar

Arrastar e soltar é uma maneira intuitiva de transferir dados em um aplicativo ou entre aplicativos na área de trabalho do Windows. Arrastar e soltar permite que o usuário transfira dados entre aplicativos ou dentro de um aplicativo usando um gesto padrão (pressionar, segurar e fazer movimento panorâmico com o dedo ou pressionar e fazer movimento panorâmico com um mouse ou uma caneta eletrônica).

APIs importantes: propriedade CanDrag, propriedade AllowDrop

A origem do gesto de arrastar, que é o aplicativo ou a área em que o gesto de arrastar é disparado, fornece os dados a serem transferidos preenchendo um objeto de pacote de dados que pode conter formatos de dados padrão, incluindo texto, RTF, HTML, bitmaps, itens de armazenamento ou formatos de dados personalizados. A origem também indica o tipo de operações a que ela dá suporte: copiar, mover ou vincular. Quando o ponteiro é liberado, ocorre a queda. O destino do gesto de soltar, que é o aplicativo ou a área abaixo do ponteiro, processa o pacote de dados e retorna o tipo de operação executada.

Durante arrastar e soltar, a interface do usuário de arrastar fornece uma indicação visual do tipo de operação de arrastar e soltar que está ocorrendo. Esse feedback visual é inicialmente fornecido pela origem, mas pode ser alterado pelos destinos à medida que o ponteiro se move sobre eles.

A funcionalidade de arrastar e soltar moderna está disponível em todos os dispositivos que dão suporte à UWP. Ela permite a transferência de dados entre ou dentro de qualquer tipo de aplicativo, incluindo aplicativos clássicos do Windows, embora este artigo se concentre na API XAML para a funcionalidade de arrastar e soltar moderna. Uma vez implementada, a operação arrastar e soltar funciona perfeitamente em todas as direções, incluindo de aplicativo para aplicativo, de aplicativo para área de trabalho e de área de trabalho para aplicativo.

Aqui está uma visão geral do que você precisa fazer para habilitar a funcionalidade de arrastar e soltar em seu aplicativo:

  1. Habilite arrastar um elemento definindo sua propriedade CanDrag como true.
  2. Compile o pacote de dados. O sistema manipula imagens e texto automaticamente, mas para outro conteúdo, você precisará lidar com os eventos DragStarting e DropCompleted e usá-los para construir seu próprio pacote de dados.
  3. Habilite a remoção definindo a propriedade AllowDrop como true em todos os elementos que podem receber conteúdo descartado.
  4. Manipule o evento DragOver para informar ao sistema que tipo de operações de arrastar que o elemento pode receber.
  5. Processe o evento Drop para receber o conteúdo descartado.

Habilitar a funcionalidade de arrastar

Para habilitar arrastar um elemento, defina sua propriedade CanDrag como true. Isso torna o elemento — e os elementos que ele contém, no caso de coleções como ListView — arrastáveis.

Seja específico sobre o que pode ser arrastado. Os usuários não desejarão arrastar tudo em seu aplicativo, apenas determinados itens, como imagens ou texto.

Veja como definir CanDrag.

<Image x:Name="Image" CanDrag="True" Margin="10,292,10,0" Height="338"></Image>

Você não precisa fazer nenhum outro trabalho para permitir arrastar, a menos que você queira personalizar a interface do usuário (que será abordada posteriormente neste artigo). A remoção requer mais algumas etapas.

Construir um pacote de dados

Na maioria dos casos, o sistema construirá um pacote de dados para você. O sistema automaticamente lida com:

  • Imagens
  • Texto

Para outro conteúdo, você precisará lidar com os eventos DragStarting e DropCompleted e usá-los para construir seu próprio DataPackage.

Habilitar a funcionalidade de soltar

A marcação a seguir mostra como a propriedade AllowDrop pode ser usada para especificar que uma área do aplicativo é um destino de soltar válido para um item arrastado (a área especificada não deve ter um plano de fundo nulo, deve ser capaz de receber entrada de ponteiro e o item não pode ser solto em nenhum lugar que não seja a área especificada).

Observação

Normalmente, um elemento de interface do usuário tem um plano de fundo nulo por padrão. Se você quiser que os usuários possam soltar um item em qualquer lugar do seu aplicativo, o plano de fundo do aplicativo não poderá ser nulo (definido Background="Transparent" se o plano de fundo não deve estar visível).

<Grid AllowDrop="True" DragOver="Grid_DragOver" Drop="Grid_Drop"
      Background="LightBlue" Margin="10,10,10,353">
    <TextBlock>Drop anywhere in the blue area</TextBlock>
</Grid>

Manipular o evento DragOver

O evento DragOver é acionado quando um usuário arrasta um item sobre seu aplicativo, mas ainda não o derrubou. Neste manipulador, você precisa especificar a que tipo de operações seu aplicativo dá suporte usando a propriedade AcceptedOperation. Copiar é a mais comum.

private void Grid_DragOver(object sender, DragEventArgs e)
{
    e.AcceptedOperation = DataPackageOperation.Copy;
}

Processar o evento Drop

O evento Drop ocorre quando o usuário libera itens em uma área de descarte válida. Processe-os usando a propriedade DataView.

Para simplificar no exemplo abaixo, vamos supor que o usuário soltou uma única foto e a acesse diretamente. Na realidade, os usuários podem descartar vários itens de formatos variados simultaneamente. Seu aplicativo deve lidar com essa possibilidade verificando quais tipos de arquivos foram descartados e quantos existem e processar cada um adequadamente. Você também deve considerar notificar o usuário se ele estiver tentando fazer algo a que o seu aplicativo não dá suporte.

private async void Grid_Drop(object sender, DragEventArgs e)
{
    if (e.DataView.Contains(StandardDataFormats.StorageItems))
    {
        var items = await e.DataView.GetStorageItemsAsync();
        if (items.Count > 0)
        {
            var storageFile = items[0] as StorageFile;
            var bitmapImage = new BitmapImage();
            bitmapImage.SetSource(await storageFile.OpenAsync(FileAccessMode.Read));
            // Set the image on the main page to the dropped image
            Image.Source = bitmapImage;
        }
    }
}

Personalizar a interface do usuário

O sistema fornece uma interface do usuário padrão para arrastar e soltar. No entanto, você também pode optar por personalizar várias partes da interface do usuário definindo legendas e glifos personalizados ou optando por não mostrar uma interface do usuário. Para personalizar a interface do usuário, use a propriedade DragEventArgs.DragUIOverride.

private void Grid_DragOverCustomized(object sender, DragEventArgs e)
{
    e.AcceptedOperation = DataPackageOperation.Copy;
    e.DragUIOverride.Caption = "Custom text here"; // Sets custom UI text
    // Sets a custom glyph
    e.DragUIOverride.SetContentFromBitmapImage(
        new BitmapImage(
            new Uri("ms-appx:///Assets/CustomImage.png", UriKind.RelativeOrAbsolute)));
    e.DragUIOverride.IsCaptionVisible = true; // Sets if the caption is visible
    e.DragUIOverride.IsContentVisible = true; // Sets if the dragged content is visible
    e.DragUIOverride.IsGlyphVisible = true; // Sets if the glyph is visibile
}

Abrir um menu de contexto em um item que você pode arrastar com toque

Ao usar o toque, arrastar um UIElement e abrir seu menu de contexto compartilham gestos de toque semelhantes; cada um começa com pressionar e segurar. Veja como o sistema desambigua entre as duas ações para elementos em seu aplicativo que dão suporte a ambos:

  • Se um usuário pressionar e segurar um item e começar a arrastá-lo dentro de 500 milissegundos, o item será arrastado e o menu de contexto não será mostrado.
  • Se o usuário pressionar e segurar, mas não arrastar dentro de 500 milissegundos, o menu de contexto será aberto.
  • Depois que o menu de contexto estiver aberto, se o usuário tentar arrastar o item (sem levantar o dedo), o menu de contexto será ignorado e o gesto de arrastar será iniciado.

Designar um item em um ListView ou GridView como uma pasta

Você pode especificar um ListViewItem ou GridViewItem como uma pasta. Isso é particularmente útil para cenários do TreeView e do Explorador de Arquivos. Para fazer isso, defina explicitamente a propriedade AllowDrop como True nesse item.

O sistema mostrará automaticamente as animações apropriadas para soltar em uma pasta em comparação com um item que não seja de pasta. O código do aplicativo deve continuar a manipular o evento Drop no item de pasta (bem como no item que não é pasta) para atualizar a fonte de dados e adicionar o item descartado à pasta de destino.

Habilitar a reordenação de arrastar e soltar em ListViews

O ListView dá suporte à reordenação pronta para uso baseada em arrastar, usando uma API muito semelhante à API CanDrop descrita neste artigo. No mínimo, você adiciona as propriedades AllowDrop e CanReorderItems.

Confira ListViewBase.CanReorderItems para obter mais informações.

Implementar arrastar e soltar personalizados

A classe UIElement faz a maior parte do trabalho de implementação de arrastar e soltar para você. Mas, se desejar, você pode implementar sua própria versão usando as APIs abaixo.

Funcionalidade API WinAppSDK
namespace Microsoft.UI.Input.DragDrop
API da UWP
Namespace Windows.Applicationmodel.DataTransfer.DragDrop.Core
DragPrimitive DragOperation CoreDragOperation
Criar um pacote de dados DataPackage mesmo
Entregar arrastado para o shell DragOperation.StartAsync CoreDragOperation.StartAsync
Receber solto do shell DragDropManager.TargetRequested
ICoreDropOperationTarget
CoreDragDropManager.TargetRequested
ICoreDropOperationTarget

Confira também