Monday, July 5, 2010

Getting Silverlight 4 Drag And Drop Working With The SharePoint 2010 Silverlight Web Part

Chris Domino, Director, Enterprise Architect

I'm working on some Silverlight 4 drag and drop functionality for a SharePoint 2010 site, and ran into the old situation where it worked fine locally, but not fine in SharePoint. What would happen is the browser, in SharePoint, actually opened the image instead of tunneling the drop event to my Silverlight control. I actually knew it wasn't going to work immediately when I noticed that the cursor was different between the two browsers: the one spawned by Visual Studio had the correct "drag" cursor, while SharePoint sported the "shortcut" one.

This was one of those problems that seemed impossible. How can I control the browser's behavior toward dragging and dropping files from a different process (such as Windows Explorer)? How could it possibly work on one site and not another? Environmental problems are much harder to solve, in my opinion, than logical problems. I can always take my code apart line by line to exterminate some bug. But when it comes to IE (in this case) being flakey, what can you do?

So I peeked behind the scenes at both markups, and found one difference between the two. "If this isn't the problem," I thought, "well, I'm going home." The difference turned out to be the Silverlight Windowless setting. This is an optional parameter that can be nestled into the object tag and takes a Boolean value.

Setting this to "true" means the Silverlight control is, well, windowless; it literally embeds itself in the browser's window instead of having the plugin define its bounds. Although there is a performance hit, this embedding allows the control to be truly transparent, and have HTML overlay or underlay it. If Windowless is "false," it sort of floats "above" the browser. Now, Silverlight is always still in the same physical window (as it's in IE's process) of course; the difference is that, if not Windowless, Silverlight acts a bit more autonomously from the browser.

The other consideration, and the one that got me here, is that setting Windowless to true precludes some of the mouse events. Since Silverlight is "in line" with the browser, then the browser will handle them. However, when it floats above (not Windowless), Silverlight can intercept these mouse events, including, of course, drag and drop!

Visual Studio, by default, does not include this parameter, and therefore Windowless defaults to false in Silverlight. The problem is that the SilverightWebPart that comes OOTB in SharePoint 2010 automatically adds this parameter, and sets it to true. And in classic SharePoint fashion, although there is Boolean .NET property that can be set programmatically, the ToolPart does not expose it on the UI.

So how do we fix this to get drag and drop working? You can always add some jQueryto the master page that blindly sets the parameter to false, but this is a little sloppy. Instead, I came up with the following code that correctly sets the WindowlessMode property on the web part, and persists it:

  1. using System;
  2. using System.Web.UI;
  3. using Microsoft.SharePoint;
  4. using System.Web.UI.WebControls.WebParts;
  5. using SPWP = Microsoft.SharePoint.WebPartPages;
  6. ...
  7. //get this page
  8. using (SPWP.SPLimitedWebPartManager mgr = SPContext.Current.Web.GetLimitedWebPartManager(this.Page.Request.Url.AbsolutePath, PersonalizationScope.Shared))
  9. {
  10. //get all web parts
  11. foreach (WebPart wp in mgr.WebParts)
  12. {
  13. //look for silverlight web parts
  14. if (wp is SPWP.SilverlightWebPart)
  15. {
  16. //disable windowless mode
  17. ((SPWP.SilverlightWebPart)wp).WindowlessMode = false;
  18. mgr.SaveChanges(wp);
  19. }
  20. }
  21. //clean
  22. mgr.Web.Close();
  23. mgr.Web.Dispose();
  24. }

This code could be a web part, a feature, or code in the master page. Run it once, and you'll be able to drag and drop files into a Silverlight 4 web part living inside of SharePoint 2010! Then reference the Client Object Model DLL in your control, and you've got the makings of a killer SharePoint 2010 uploader control, using one of the coolest new features of Silverlight.

Have fun!