Desenvolvimento - WPF

Drag e Drop de arquivos em WPF

Veja neste artigo como implementar a função de Drag e Drop (arrastar e soltar) com arquivos em uma aplicação WPF.

por Joel Rodrigues



Operações de Drag and Drop (arrastar e soltar) são bastante comuns nos mais diversos tipos de aplicações. Atualmente essa ação é utilizada, por exemplo, para arrastar arquivos do computador para o browser, de forma a anexá-lo a um e-mail ou fazer upload em um sistema qualquer.

Diversos plug-ins de upload já contam com essa funcionalidade, que na maior parte dos casos, poupa o usuário de precisar navegar por diversas pastas no sistema de arquivos utilizando uma caixa de diálogo.

Neste artigo veremos como implementar essa funcionalidade em aplicações desktop WPF, permitindo que o usuário arraste arquivos de uma pasta qualquer para a aplicação, a fim de realizar algum procedimento de upload (como anexar um arquivo a uma ficha de cliente, como documentos digitalizados, por exemplo).

Neste exemplo teremos um controle ListBox sobre o qual o usuário poderá soltar os arquivos, e então o caminho do arquivo será adicionado à lista de itens. Ao final, teremos um botão que copiará todos os arquivos adicionados à lista para uma pasta especificada.

Para que o ListBox aceite a operação de Drop, é necessário definir sua propriedade AllowDrop como True. Em seguida, é preciso tratar o evento Drop para ler o conteúdo arrastado até a lista, através do argumento do tipo DragEventArgs.

A Listagem 1 mostra o código XAML da janela principal da aplicação de exemplo. Observe que já foram definidos os Event Handlers para os eventos Drop do ListBox e Click do Button, assim como a propriedade AllowDrop.

Listagem 1. Código XAML da janela de upload

  <Window x:Class="WpfApplication1.MainWindow"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
          xmlns:local="clr-namespace:WpfApplication1"
          mc:Ignorable="d"
          Title="MainWindow" Height="350" Width="525">
      <Grid>
          <Grid.RowDefinitions>
              <RowDefinition Height="30"/>
              <RowDefinition Height="*"/>
              <RowDefinition Height="30"/>
          </Grid.RowDefinitions>
          <TextBlock Text="Anexar arquivos" FontSize="20" Grid.Row="0"/>
          <ListBox Name="listArquivos" Grid.Row="1" AllowDrop="True" Drop="listArquivos_Drop"/>
          <Button Name="btnSalvar" Grid.Row="2" Content="Salvar" Click="btnSalvar_Click"/>
      </Grid>
  </Window>

Executando a aplicação teremos um layout bem simples, como mostra a Figura 1.

Layout da janela de upload

Figura 1. Layout da janela de upload

O próximo passo é tratar o evento Drop no código C# da janela. No método listArquivos_Drop precisamos primeiramente identificar se é um arquivo que está sendo solto sobre lista. Isso pode ser feito verificando se a informação com a chave FileName está contida nos dados que foram dropados. Em caso positivo, obtemos o nome do arquivo com o método GetData do objeto e.Data o adicionamos à lista, conforme mostra o código da Listagem 2.

Listagem 2. Tratamento do evento Drop do ListBox

  private void listArquivos_Drop(object sender, DragEventArgs e)
  {
      if (e.Data.GetDataPresent("FileName"))
      {
          string fileName = (e.Data.GetData("FileName") as string[])[0];
          listArquivos.Items.Add(fileName);                
      }
  }

Executando a aplicação e arrastando um arquivo para o ListBox teremos o caminho do arquivo adicionado à lista, conforme ilustra a Figura 2.

Arquivos arrastados e soltos sobre o ListBox

Figura 2. Arquivos arrastados e soltos sobre o ListBox

Feito isso, podemos tratar o evento Click do botão para copiar os arquivos listados. Para isso, basta que utilizemos o método Copy da classe File, passando o caminho contido na lista e um novo caminho. A Listagem 3 contém o código para efetuar esse procedimento.

Listagem 3. Copiando os arquivos listados

  private void btnSalvar_Click(object sender, RoutedEventArgs e)
  {
      foreach (var item in listArquivos.Items)
      {
          File.Copy(item.ToString(),
              System.IO.Path.Combine("E:\\", new FileInfo(item.ToString()).Name));
      }
  }

Façamos agora um segundo exemplo no qual permitiremos arrastar uma imagem para a janela e quando soltá-la esta será usada como plano de fundo. Neste exemplo não será necessário ter nenhum controle adicional na janela, bastando que a propriedade AllowDrop seja definida como True e o evento Drop tratado. Sendo assim, a Listagem 4 mostra o código XAML da janela.

Listagem 4. Código XAML da janela vazia

  <Window x:Class="WpfApplication1.MainWindow"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
          xmlns:local="clr-namespace:WpfApplication1"
          mc:Ignorable="d"
          Title="MainWindow" Height="350" Width="525"
          AllowDrop="True" Drop="Window_Drop">
      <Grid>
          
      </Grid>
  </Window>

Na sequência, basta tratar o evento Drop no código C# da janela para verificar se o arquivo recebido é uma imagem e então defini-la como background. O código que implementa essa funcionalidade é apresentado na Listagem 5 a seguir.

Listagem 5. Tratando a imagem arrastada e solta sobre a janela

  private void Window_Drop(object sender, DragEventArgs e)
  {
      if (e.Data.GetDataPresent("FileName"))
      {
          string fileName = (e.Data.GetData("FileName") as string[])[0];
          FileInfo fInfo = new FileInfo(fileName);
          if(fInfo.Extension == ".png" || fInfo.Extension == ".jpg")
          this.Background = new ImageBrush(new BitmapImage(new Uri(fileName)));
      }
  }

Neste código verificamos se está sendo arrastado um arquivo e se a sua extensão corresponde a uma imagem válida (aqui consideramos apenas PNG e JPG como válidas). Em caso positivo, criamos um novo ImageBrush a partir da imagem copiada e o atribuímos à propriedade Background da janela (this).

O resultado é demonstrado na Figura 3.

Background da janela alterado após arrastar imagem até ela

Figura 3. Background da janela alterado após arrastar imagem até ela

São diversas as possibilidades de uso dessa funcionalidade. Espero que aproveitem os códigos disponibilizados.

Links

Drag and Drop Overview – MSDN
https://msdn.microsoft.com/en-us/library/ms742859%28v=vs.110%29.aspx

Joel Rodrigues

Joel Rodrigues - Técnico em Informática - IFRN Cursando Bacharelado em Ciências e Tecnologia - UFRN Programador .NET/C# e Delphi há quase 3 anos, já tendo trabalhado com Webservices, WPF, Windows Phone 7 e ASP.NET, possui ainda conhecimentos em HTML, CSS e Javascript (JQuery).