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 o movimento do tipo "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 definir uma área específica do aplicativo como válida para descarte usando o AllowDrop em XAML. Se um usuário tentar soltar em outro lugar, o sistema não permitirá. Se você quiser que os usuários possam descartar itens em qualquer lugar em seu aplicativo, defina toda a tela de fundo como um destino para soltar.

<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