tl;dr: The code in this post supports file drag-and-drop in Silverlight 4 on Firefox on Mac OS X (as well as Safari on OS X, though that's with JS already available on the Internet). Code download is at the end of the post.
Silverlight is great for building rich cross-browser web applications, especially for internally-facing applications where it’s ok to require the installation of the Silverlight runtime. Why? Because it works pretty much the same on all the supported environments and browsers. I don’t have to worry about the wacky HTML differences that are IE 6 and how they differ from IE 9, Firefox, Chrome, and Safari. I can do real transparency and rounded corners without having to cut 500 images and overlay DIVs in a slick way to achieve the visual effect the designer is looking for (and then test it on every browser/platform combination). I can use a real strongly-typed language on the client, get full data binding support, great Intellisense from Visual Studio, and oh yeah - WCF 4 RIA Services is *really nice*. All great things.
(the above code will only work with Firefox, as Chrome/Safari don’t support .getDataAsUrl on the file object. Getting it working there should just require using the HTML5 File API, but I haven’t looked into it – see http://www.thebuzzmedia.com/html5-drag-and-drop-and-file-api-tutorial/ if you’re interested, and send me a link (or the code) if you get it figured out)
So, how do I apply this to my project you ask?
Now for Silverlight. You’ll need these .cs files from the ‘SLDragDrop’ project:
- BrowserConsole.cs (wrappers around the browser’s console.log support so you can call it from Silverlight. Very useful if you aren’t using logging of some other kind, like Clog)
- FileDragAndDrop.cs (the behavior and attached properties to use with it – the behavior implementation extends Prism’s commanding infrastructure. If you’re not using Prism, use the base class from your MVVM implementation of choice, or just do that wiring yourself)
- IFileInfo.cs (the IFileInfo interface and some extensions to work with it)
- Utilities.cs (works around an issue with string.IndexOf on Macs that Chris Domino discovered)
The other files are part of the example usage of it (App.xaml, ImagePreviewConverter.cs, MainPage.Xaml, and ViewModel.cs).
I’m guessing your ViewModel will have more interesting logic in OnDrop, but this will service for now. In your View, define a prefix for the XAML namespace your FileDragAndDrop class is in, like this:
Then, define the control you want to be drag-and-dropable:
FileDragAndDrop.Command is the only thing required to make this work, but we found working with users, they better understood where to drop files if the UI changed in some way when they hovered over the element with a file – the DragEnterVisualState and DragLeaveVisualState properties specify a VisualState to transition to when the drag event starts and ends. In the sample project, I use it to light up the background of the ContentControl during the drag operation.
The last piece is to call FileDragDropHelper.Enable with the root visual of your application (it’ll use this to attach the needed event handlers). I do this in the Loaded event on my main visual:
And there you have it – a Silverlight 4 FileDragAndDrop behavior via an attached command that actually works on Firefox on a Mac. (and with a little more tweaking, would probably work on Chrome on a Mac too).