23 Nov
2009

Silverlight 4 Beta – Using Silverlight as Drop Target

Category:UncategorizedTag: , , :

Have you ever wanted to give the user the ability to drag a file from you desktop or file explorer onto your Silverlight application? Well, up until now you couldn’t. What’s that sound? It’s a bird… it’s a plane… no, it’s Silverlight 4 Beta.  Yes, Silverlight 4 Beta is coming to the rescue and giving you the ability to have your Silverlight application act as a drop target. And it is so easy to do. Observe.

First just identify the UI element you want to use as the drop target, then set the AllowDrop property to true. Then just handle the Drop events.

Here is a quick example. This examples allows a user to drag a bitmap from their file system into my application and displays the images in a ScrollViewer. Here is the XAML

<StackPanel x:Name="LayoutRoot" Background="White">

    <TextBlock Text="Drop image below." FontSize="16" FontWeight="BOld" HorizontalAlignment="Center" />

    <ScrollViewer x:Name="ImagesTarget" Background="White" Width="800" MinHeight="300" 

                  VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Auto" AllowDrop="True">

            <ItemsControl x:Name="ImageList">

                <ItemsControl.ItemTemplate>

                    <DataTemplate>

                        <Image Source="{Binding}" Margin="5" Stretch="UniformToFill" Height="240" />

                    </DataTemplate>

                </ItemsControl.ItemTemplate>

                <ItemsControl.ItemsPanel>

                    <ItemsPanelTemplate>

                        <StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center"/>

                    </ItemsPanelTemplate>

                </ItemsControl.ItemsPanel>

            </ItemsControl>

        </ScrollViewer>

</StackPanel>

I create a ObservableCollection of bitmap images and use this as the ItemsSource for the ScrollViewer.

ObservableCollection<BitmapImage> _images = new ObservableCollection<BitmapImage>();

I hook into the Drop event in the load event of the form.

ImagesTarget.Drop += new DragEventHandler(ImagesTarget_Drop);

Now lets implement the Drop event to loop through all the files and add them to the list.

void ImagesTarget_Drop(object sender, DragEventArgs e)

{

    if (e.Data == null)

        return;

 

    IDataObject dataObject = e.Data as IDataObject;

    FileInfo[] files =

      dataObject.GetData(DataFormats.FileDrop) as FileInfo[];

 

    foreach (FileInfo file in files)

    {

        try

        {

            using (var stream = file.OpenRead())

            {

                var imageSource = new BitmapImage();

                imageSource.SetSource(stream);

                _images.Add(imageSource);

            }

        }

        catch (Exception)

        {

            MessageBox.Show("Not a suppoted image.");

        } 

    } 

}

Bingo… Bango… Boom, that is all there is to it. And of course, you can handle the other drag events to have more control over what is being dropped and where.

Download the Source

10 thoughts on “Silverlight 4 Beta – Using Silverlight as Drop Target

  1. I’ve been playing with this code and it’s great! We’ve been after a drag target solution for a while and this could well be it.

    I’m currently looking at extending this further to include file info on the objects added and also a remove function although i’m currently stuck on that bit…

  2. I’ve got the remove image working but really I’m looking to drag emails from Outlook and capture them in a Silverlight control in a similar fashion to what is happening in your article. I’ve tried a few things but it will only allow the drag and drop from a .msg file on the file system rather than from Outlook itself.

    Any thoughts?

  3. @Dan Fell

    Well, getting mail items from Outlook isn’t as easy as one might think. In WPF land I use Microsoft.Office.Interop.Outlook to accomplish this task:

    ApplicationClass app = new ApplicationClass();
    Selection sel = app.ActiveExplorer().Selection;
    string path = @”c:\DroppedMessages\”;
    foreach (object mitem in sel)
    {
    MailItem mi = (MailItem)mitem;
    string fileName = string.Format(“{0}{1}.msg”, path,
    mi.Subject.Replace(“:”, “”));
    mi.SaveAs(fileName, OlSaveAsType.olMSG);
    }

    I haven’t tried this in Silverlight yet, but just to get a list of file names of mail items without using interop assemblies you would have to do this.

    Stream fileContentNames = (Stream)e.Data.GetData(“FileGroupDescriptor”);
    byte[] fileContentNameBytes = new byte[fileContentNames.Length];
    fileContentNames.Read(fileContentNameBytes, 0,
    fileContentNameBytes.Length);
    fileContentNames.Close();

    StringBuilder fileName = new StringBuilder(“”);

    for (int i = 76; fileContentNameBytes[i] != 0; i )
    {
    fileName.Append(Convert.ToChar(fileContentNameBytes[i]));
    }

    Now getting the actual contents fo the mail message is a whole other story. Good luck.

  4. Any advice would be appreciated, I took the code you presented here and put it in a brand new SL4 application, but under no circumstances could I drop a file into the running app. I am facing the exact same problem with the example from Jesse Liberty- same code as presented, tried regular and OOB, but regardless I cannot drop a file into my SL app.

    Any recommendations? 🙂

  5. Well, I can’t really tell you what the problem is without seeing your code. Just make sure you are not trying to drop into a container control, like a grid, without setting a background color. If you try to drop into a grid, you would have to drop it exactly on the edge which is very difficult to do. Try it with a button, if it works with a button, then you are not doing something quite right. Also, make sure your application is targeting the correct framework. Also, check your output window to check for any errors that may be occuring.

  6. Well I’m mystified. I downloaded the solution, opened and ran it from VS2010, and tried to drag a .jpg from my Pictures library onto the rectangle in the app, and it wouldn’t work… the cursor never changed from the “you can’t drop here” circle-with-a-slash image. I had the same behavior using an image control as a drop target in my own app. I am using SL4 GA. Any thoughts? I am totally stumped.

Comments are closed.