Mike Taulty's Blog
Bits and Bytes from Microsoft UK
Silverlight 4 Rough Notes: Silverlight as a Drop Target

Blogs

Mike Taulty's Blog

Elsewhere

Note – these posts are put together after a short time with Silverlight 4 as a way of providing pointers to some of the new features that Silverlight 4 has to offer. I’m posting these from the PDC as Silverlight 4 is announced for the first time so please bear that in mind when working through these posts.

One of the desktop integration features that people want from business applications is the ability to drag and drop.

Silverlight 4 has new functionality that lets you use a Silverlight application as a drop target – that is, files that come from the desktop can be dragged into a Silverlight application but not the other way around.

This is really easy to enable. On the UIElement class, there’s a new property called AllowDrop which is just a bool indicating whether the element allows file drops or not.

There are also a bunch of events DragEnter, DragLeave, DragOver, Drop to support drag-and-drop.

So, with a simple UI such as this one;

<UserControl x:Class="SilverlightApplication8.MainPage"
    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"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition
                Height="Auto" />
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <CheckBox
            Margin="10"
            Content="Allow File Drop"
            IsChecked="{Binding ElementName=rect,Path=AllowDrop,Mode=TwoWay}" />
        <Rectangle
            x:Name="rect"
            Fill="Red"
            Grid.Row="1"
            Margin="10" 
            DragEnter="OnDragEnterEvent"
            DragLeave="OnDragLeaveEvent"
            DragOver="OnDragOverEvent"
            Drop="OnDropEvent"
            MinHeight="96"/>
        <ListBox
            ItemsSource="{Binding Images}"
            Grid.Row="2"
            Margin="10">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Image
                        Source="{Binding .}"
                        Width="96"
                        Height="96"
                        Margin="10" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</UserControl>

I can write a little code-behind;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Text;
using System.Collections.ObjectModel;
using System.IO;
using System.Windows.Media.Imaging;

namespace SilverlightApplication8
{
  public partial class MainPage : UserControl
  {
    public MainPage()
    {
      InitializeComponent();

      this.Loaded += (s, e) =>
        {
          this.Images = new ObservableCollection<BitmapImage>();
          this.DataContext = this;          
        };
    }
    public ObservableCollection<BitmapImage> Images { get; set; }

    private void OnDragEnterEvent(object sender, DragEventArgs e)
    {
      rect.Fill = new SolidColorBrush(Colors.Green);
    }
    private void OnDragLeaveEvent(object sender, DragEventArgs e)
    {
      rect.Fill = new SolidColorBrush(Colors.Red);
    }
    private void OnDragOverEvent(object sender, DragEventArgs e)
    {
      rect.Fill = new SolidColorBrush(Colors.Yellow);
    }
    private void OnDropEvent(object sender, DragEventArgs e)
    {
      // Was it a file drop? ( should be as it's the only type of drop )
      if ((e.Data != null) &&
        (e.Data.GetDataPresent(DataFormats.FileDrop)))
      {
        // Woohoo!
        FileInfo[] files = e.Data.GetData(DataFormats.FileDrop) as FileInfo[];

        if (files != null)
        {
          foreach (FileInfo fileInfo in files)
          {
            using (FileStream fs = fileInfo.OpenRead())
            {
              BitmapImage bi = new BitmapImage();
              bi.SetSource(fs);

              this.Images.Add(bi);
              fs.Close();
            }
          }
        }       
      }
      OnDragLeaveEvent(null, null);
    }
  }
}

and that easily lets me drag-and-drop files from the desktop ( either as single files or as multiple sets of files ) and drop them onto the Rectangle in my UI and then I pick up that Drop event and attempt ( without much error handling ) to load those files as Images into a ListBox.

Neat.

As an aside – I found that trying to interrogate the DragEventArgs.Data whilst the drag operation is in flight ( i.e. rather than when you actually get the Drop event ) gave me a security exception and I suspect that’s part of the design so take care on that one.


Posted Wed, Nov 18 2009 11:13 AM by mtaulty
Filed under: ,

Comments

Imgen wrote re: Silverlight 4 Rough Notes: Silverlight as a Drop Target
on Wed, Nov 18 2009 7:01 PM

Really impressive. That's exactly what I want. I'm so pleased to hear that this feature is finally enabled.

jo wrote re: Silverlight 4 Rough Notes: Silverlight as a Drop Target
on Sat, Nov 21 2009 1:45 PM

Hi,

I've got SL4Beta but above code doesn't work..

It compiles ok, but when I drag files over SL control I get crossed circle indicating that drop is not possible.

Can you think of anything else that has to be done to enable this functionality?

mtaulty wrote re: Silverlight 4 Rough Notes: Silverlight as a Drop Target
on Mon, Nov 23 2009 2:35 AM

Hi Jo,

Not sure what's going on for you here - I was a little worried so I just copied/pasted the code and XAML from the site here and it works fine for me in that I can drag/drop images onto the SL control without error.

If you want to send me a project, I'll take a look.

Thanks,

Mike.

Gordon Mackie wrote re: Silverlight 4 Rough Notes: Silverlight as a Drop Target
on Thu, Nov 26 2009 5:55 AM

You also get security exceptions if you try to query the Directory and DirectoryName properties of the FileInfo objects you get from e.Data.GetData call. Also it doesn't seem to be possible to distinguish between a file and a directory in a list of FileInfo objects if you drag and drop a selection from an Explorer window. As such it wouldn't be possible to open a directory and walk its contents either, security exceptions notwithstanding.

Gordon Mackie wrote re: Silverlight 4 Rough Notes: Silverlight as a Drop Target
on Tue, Dec 1 2009 3:43 AM

After more investigation - it's all about elevated permissions and running OOB. I blogged an example of dragging files and directories to a Silverlight app and building a TreeView representation: joanmiro.blogspot.com/.../five-minute-silverlight-4-aides-memoire.html