We’ve now added better support for drag and drop in the latest version of Azure Management Studio (AMS). In this version you can drag block blobs both into and out of the AMS folder views.
So, for example, in the pictures below I drag a single selected file across AMS onto the desktop.
When you start the dragging, you cannot drop to start with (as you’d be copying the file into the folder that contains it), so the no drop annotation is displayed. We use the Windows shell to get a suitable graphic to display next to the cursor, so here we see its representation of a png image file.
Once the cursor is above a target that does support a drop, the drop description changes to reflect the action that will happen if you release the mouse and start the drop.
Of course, we don’t just support drag and drop inside the tool, but also allow other applications to accept the drop. In particular the shell is happy to take the drop of a data stream that we offer it.
When the user elects to drop onto a folder, this will make AMS fetch the blob content and stream it to the shell as a byte stream. The shell can use the name information included within the transfer object to create a file of the correct name which it can then fill with the content.
Of course, we don’t just want to be able to drag blobs out of AMS. We have also improved AMS so that it can handle more types of items that are dragged on to it. Drag and drop is a little complicated, and we’ll try to give a better overview of it below, but essentially the drop target (AMS) can look at the formats of the data which the source offers. Typically a source may offer a list of files on the local file system, and we have been able to handle this kind of source for a long time in AMS. If you drag a file out of a zip file though, this is offered to the target as a byte stream (plus some metadata) and AMS now knows how to handle this kind of information.
When you drag one or more of the files contained in a .zip file:
AMS happily accepts that as a drop target:
And dropping leads to a transfer executing, which is logged in the transfer panel:
As we’ll discuss in a moment, copy and paste uses a fairly similar mechanism behind the scenes so will work in the same way.
So how does Drag and Drop work then?
Drag and drop has been around since the old days and relies on COM interfaces to do its work. It revolves around the IDataObject interface. which essentially describes a dictionary which interested parties can both query for various properties (that correspond to different renderings of data). and also set properties to reflect the progress of any data transfer that is happening.
When a drag operation is started, the source makes an instance of this class, populates it with relevant data and then calls into a shell helper method passing the DataObject as one of the arguments. This shell helper method will then take care of executing the drag as the cursor moves across the screen, interacting with the drop sources that are passed over in the process, until the drop happens on a particular target or it is cancelled (by pressing the Escape key). If you drag from AMS then we put at least two renderings of the data into the DataObject – one that is a serialized .NET object that only AMS understands. which it will use if you drag from AMS into itself, and a second data format that offers the data as a stream. In this second format. the data is offered as a set of metadata about the name of the item together with an OLE stream which the target can use to pull the data in blocks of bytes.
The DataObject is also used to reflect the semantics of the action itself. The target can set values to reflect whether it wants the action to be a move or a copy, and it will also set a value to say whether the drop was successful and whether the source needs to carry out the delete part of any Move. It will also populate the DataObject with the drag image which is shown by a window that the shell creates next to the cursor when you are dragging, and potentially a piece of description text describing the operation.
When the cursor moves over a potential drop target, this target gets a callback and can then freely interrogate the DataObject to determine if it contains suitable data for it to process. It can return a result back to the shell, which can use this to determine which cursor it displays – one showing that the drop is available or the no entry sign which reflects that the target isn’t able to handle the data that is being dragged. The target is also free to change the displayed text.
How do I do it then?
There are many useful blog posts out there that cover the rather arcane methods involved.
One ends up working at the level of COM which is supported fairly well inside .NET. The only lacking feature (as far as I know) is a way to detect that the COM object is no longer being used by external parties via COM… in C++ one can keep an eye on the reference count, but in the .NET world there is no way to see if the .NET created CCW (COM callable wrapper) is being used, and so the only way to detect that the object is no longer used is to add a Finalizer to its type.
You also go back to the days of managing your own memory, with you being needed to do Global Lock and Unlock, and also allocate using Marshal.AllocHGlobal.
There are also a few extra interfaces you might want to implement – IAsyncOperation, for example, which allows the Shell to do a data transfer without blocking.
Getting all these parts to work together took some effort, and was helped a fair amount by a working implementation of some of this inside the Azure Explorer tool that we have made freely available for some time. We started with the Azure Explorer implementation and then merged in bits and pieces from various blog posts as we needed more functionality.
The good news is that you almost get cut-and-paste for free after you’ve done the work implementing drag and drop, as this transfer process is also centred on the idea of a DataObject. The key difference is that you place the DataObject on the clipboard for other applications to find, and in order to enable your paste menu you may need to subscribe to clipboard change events so see if the clipboard contains a suitable format.
Was it worth it?
When you are dealing with the file system on your local machine, and something like Blob storage which is typically displayed using a folder and files metaphor, it feels more natural to drag and drop files around, and have the system interpret this as a series of transfer operations.
Hopefully, our users will find it useful.
To try out this new feature download your free trial of Azure Management Studio now. Existing users can get the latest version from within Azure Management Studio (go to Help – Check for Updates).