Archive
HowTo: Drop files onto Silverlight controls
I was recently adding drop-files support to ClipFlair Studio, so I had to do some research on the related API that is available to Silverlight apps.
Silverlight supports a limited set of Drag-and-Drop interaction with the operating system (supposedly for security reasons, but most probably because of the classic cross-platform implementation pains).
For example it allows you to drop a collections of file objects from the operating system’s file explorer (or other similar application) onto a Silverlight drop target, but not the other way around.
Also, it doesn’t allow dropping other flavors of content, like text, images etc., only collections of file objects.
To allow dropping files onto a Silverlight control you set AllowDrop property to true and handle the Drop and optionally the DragEnter/DragOver/DragLeave events to provide visual feedback during the drop operation (mostly when over the drop target, unless you do Mouse Capturing).
<RichTextBox
x:Name="rtb"
…
AllowDrop="True"
Drop="rtb_Drop"
DragEnter="rtb_DragEnter"
DragOver="rtb_DragOver"
DragLeave="rtb_DragLeave"
/>
#region DragAndDrop
private void rtb_Drop(object sender, System.Windows.DragEventArgs e)
{
VisualStateManager.GoToState(this, "Normal", true);//the Drop event passes in an array of FileInfo objects for the list of files that were selected and drag-dropped onto the RichTextBox.
if (e.Data == null)
return;IDataObject f = e.Data as IDataObject;
if (f != null) //checks if the dropped objects are files
{
object data = f.GetData(DataFormats.FileDrop); //Silverlight only supports FileDrop
FileInfo[] files = data as FileInfo[]; //…GetData returns null if format is not supportede.Handled = true;
if (files != null)
//Walk through the list of FileInfo objects of the selected and drag-dropped files and parse the .txt and .docx files
//and insert their content in the RichTextBox.
foreach (FileInfo file in files)
Load(file, false);
}}
private void rtb_DragEnter(object sender, System.Windows.DragEventArgs e)
{
VisualStateManager.GoToState(this, "DragOver", true);
e.Handled = true;
}
private void rtb_DragOver(object sender, System.Windows.DragEventArgs e)
{
e.Handled = true;
//NOP
}private void rtb_DragLeave(object sender, System.Windows.DragEventArgs e)
{
VisualStateManager.GoToState(this, "Normal", true);
e.Handled = true;
}#endregion
For the visual feedback you can use VisualStateManager and respective VisualStates at say a Grid that wraps the drop target in the XAML layout.
<Grid x:Name="LayoutRoot">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="DragStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.3">
<VisualTransition.GeneratedEasingFunction>
<CircleEase EasingMode="EaseIn"/>
</VisualTransition.GeneratedEasingFunction>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal"/>
<VisualState x:Name="DragOver">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Control.Background).(SolidColorBrush.Color)" Storyboard.TargetName="rtb">
<EasingColorKeyFrame KeyTime="0" Value="#FFFFF7D1"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
Note that on MacOS-X Safari doesn’t pass drop events automatically to plugins and you have to catch them via Javascript and pass them to Silverlight, plus I’ve read that in MacOS-X Firefox doesn’t support this at all.
Even worse, Microsoft’s workaround article has a typo in the Javascript (should call dragDrop instead of drop) and there is a chance it doesn’t work in latest version of Safari. For more see:
http://msdn.microsoft.com/en-us/library/ee670998%28v=vs.95%29.aspx
http://www.telerik.com/forums/dropping-files-using-safari-on-mac (this says one can use HTML5 events and the Silverlight HTML/Javascript Bridge to notify Silverlight)
http://www.thebuzzmedia.com/html5-drag-and-drop-and-file-api-tutorial/
Windows 7 issue: can’t copy filename of files on read-only media
Just came across one more case of trying to over-protect users and in the way losing functionality (maybe originally unforeseen functionality, but which is nevertheless useful to many end-users).
At Windows 7, Microsoft doesn’t allow you anymore to press F2 or click on a filename to enter edit more for it when the file resides on a read-only media (like a DVD-ROM).
Moreover when you right click the file and select Properties, the filename field at the properties dialog is at a disabled editbox and somebody from the Windows UI team must have taken “disabling” an editbox literally, making the action disable even selecting and copying text from it instead of just making it read-only.
So one would think they would be able to right-click the file, select Copy and then Paste the filepath onto an editbox. No, again no one thought of also putting a text flavor with the full file path on the clipboard so that user could paste it to a textbox (Clipboard supports multiple data flavours for copied items and when you paste an app can select which flavours it knows and might care to use). Think I have suggested that to Microsoft long time ago, but still not implemented.