Saturday, November 28, 2009

Silverlight 4 - Drag and drop images on a Silverlight application

One of the great new features of Silverlight 4 is drag-drop. This makes it possible to drag files from your OS onto the Silverlight application.

 

In this tutorial we’ll create a ListBox and make it possible to drop images from the desktop onto the application. The images will then appear in the ListBox.

 

First steps

First of all we’ll create a “normal” Silverlight 4 App + Website using Visual Studio 2010 or Expression Blend.

Next we need a ListBox to show the images when they are dropped on it. Make sure your XAML looks similar to this:

<UserControl x:Class="DragDrop.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
="328" d:DesignWidth="514">

<Grid x:Name="LayoutRoot" Background="White">
<ListBox Height="Auto" HorizontalAlignment="Left" Name="listBox1" VerticalAlignment="Stretch" Width="200" />
</Grid>
</UserControl>


Hooking it up



Next step is to create an eventhandler for the drop event. But first we need to make sure that it is allowed to drop objects onto the ListBox.



This is done by setting the AllowDrop property of the ListBox to true.



So with the addition of that line your code should look similar to this:



public MainPage()
{
InitializeComponent();
listBox1.AllowDrop
= true;
listBox1.Drop
+= new DragEventHandler(listBox1_Drop);
}

void listBox1_Drop(object sender, DragEventArgs e)
{
throw new NotImplementedException();
}


Getting the file(s) from the DragEventArgs



Now that we have everything hooked up it is time to get started with the real stuff :)



 



At this time Silverlight 4 beta only has one so called DataFormat available. With this DataForm we can retrieve the file(s) dropped onto out ListBox:



System.IO.FileInfo[] fileInfos = e.Data.GetData(DataFormats.FileDrop) as System.IO.FileInfo[];
foreach (FileInfo fileInfo in fileInfos)
{

}




The code above goes in the listbox1_Drop eventhandler.



 



Helper methods



All that is left is to add the images that were dropped to the ListBox. Before Creating the Image objects we need to make sure that the files are indeed images. All we can do to check this is to check the extension of the file.

The following method can be used to check the files:



private bool IsImageFile(string p)
{
switch (p.ToLower())
{
case ".jpg":
case ".png":
return true;
default:
break;
}
return false;
}


Now that we are pretty certain the files are images, we can create Image objects out of them. For this functionality we can use the following method:



private Image CreateImageFromFile(System.IO.FileInfo fileInfo)
{
using (FileStream fileStream = fileInfo.OpenRead())
{
BitmapImage bitmap
= new BitmapImage();
bitmap.SetSource(fileStream);
Image image
= new Image();
image.Source
= bitmap;
image.Width
= 50;
image.Stretch
= Stretch.Uniform;
return image;
}
}


 



Wrapping it up



Now all that is left for us to do is put the things together we created in the previous section.



In the foreach loop we created before, we’ll check if the files are images and if true, add them to the ListBox:



if (IsImageFile(fileInfo.Extension))
{
listBox1.Items.Add(CreateImageFromFile(fileInfo));
}


 



The entire code-behind should look something like this:



 



public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
listBox1.AllowDrop
= true;
listBox1.Drop
+= new DragEventHandler(listBox1_Drop);
}

void listBox1_Drop(object sender, DragEventArgs e)
{
System.IO.FileInfo[] fileInfos
= e.Data.GetData(DataFormats.FileDrop) as System.IO.FileInfo[];
foreach (FileInfo fileInfo in fileInfos)
{
if (IsImageFile(fileInfo.Extension))
{
listBox1.Items.Add(CreateImageFromFile(fileInfo));
}
}
}

private Image CreateImageFromFile(System.IO.FileInfo fileInfo)
{
using (FileStream fileStream = fileInfo.OpenRead())
{
BitmapImage bitmap
= new BitmapImage();
bitmap.SetSource(fileStream);
Image image
= new Image();
image.Source
= bitmap;
image.Width
= 50;
image.Stretch
= Stretch.Uniform;
return image;
}
}

private bool IsImageFile(string p)
{
switch (p.ToLower())
{
case ".jpg":
case ".png":
return true;
default:
break;
}
return false;
}
}


 



That’s it!



 



You can download the source here



 



Don’t forget to subscribe on the homepage of this site so we can keep you posted! And there’s a feed available for blogposts and news as well, so subscribe to that as well if you’re interested!

4 comments:

  1. Hi Rob,

    I read your article:
    http://web-snippets.blogspot.com/2008/06/creating-sketch-application-in_23.html

    I'm wondering if Silverlight allow us to compress files on client-side and then upload them to a remote server.
    As I saw your code:
    void SaveButton_Click(object sender, RoutedEventArgs e)
    {
    SaveDrawingService.SaveDrawingServiceSoapClient wsclient = new SaveDrawingService.SaveDrawingServiceSoapClient();

    // A memory stream to write to
    using (MemoryStream zippedMemoryStream = new MemoryStream())
    {
    // A ZIP stream
    using (ZipOutputStream zipOutputStream = new ZipOutputStream(zippedMemoryStream))
    {
    // Highest compression rating
    zipOutputStream.SetLevel(9);

    byte[] buffer;

    // The string to use as file content
    using (MemoryStream file = new MemoryStream(Encoding.UTF8.GetBytes(Lib.XMLHelpers.CreateXElementsFromStrokeCollection(inkpresenter.Strokes).ToString())))
    {
    buffer = new byte[file.Length];
    file.Read(buffer, 0, buffer.Length);
    }

    // Write the data to the ZIP file
    ZipEntry entry = new ZipEntry("drawing.xml");
    zipOutputStream.PutNextEntry(entry);
    zipOutputStream.Write(buffer, 0, buffer.Length);

    // Finish the ZIP file
    zipOutputStream.Finish();
    }

    Is it compressing on client memory?

    ReplyDelete
  2. Hi George,

    Yes, because Silverlight is a clientside technology it is using the resources of the client to zip the file(s) before uploading it to the server.

    Rob

    ReplyDelete
  3. Inspirational to say the least! Some gorgeous imaginations at work!

    ReplyDelete
  4. You have done a marvelous job! I am really inspired with your work.

    ReplyDelete