How to get data from Drag 'n Dropdown file that is not saved to disk
How can I read the xml content of an xml file that is not saved anywhere on disk?
I want to be able to drag and drop an attachment from Outlook (file extension is the usual one) and leave it in my application. Based on the content of the xml file, I will take the appropriate action.
I have tried iterating through e.Data.GetFormats()
and GetData(format)
to no avail. I tried e.Data.GetData("FileContents")
didn't work. I tried e.Data.GetData(DataFormat.Text)
also DataFormats.UnicodeText
, DataFormats.FileDrop
and nothing works.
It's important to read the contents of the file from DataObject
, as I don't want to force the user to save the file before dragging and dropping it.
Any help would be greatly appreciated!
ANSWER
Well-formatted answer for those who have the same question:
This way, any file saved to the discarded disk will have a full path that can be loaded and read.
Any file deleted from Outlook will have a "FileGroupDesciptor" to get the filename along with its extension. "FileContents" will contain the content stream.
Example:
Process dragged files to see if we can do some action
public void DragEnter(DragEventArgs e)
{
var obj = e.Data as DataObject;
//get fileName of file saved on disk
var fileNames = obj.GetFileDropList();
if(fileNames.Count > 0)
fileName = fileNames[0]; //I want only one at a time
//Get fileName not save on disk
if (string.IsNullOrEmpty(fileName) && obj.GetDataPresent("FileGroupDescriptor"))
{
var ms = (MemoryStream)obj.GetData("FileGroupDescriptor");
ms.Position = 76;
char a;
while ((a = (char)ms.ReadByte()) != 0)
fileName += a;
}
if (fileName.Length != 0)
{
var extension = fileName.Substring(fileName.LastIndexOf('.') + 1);
switch (extension.ToUpper())
{
case "WTV":
itemType = DropItemType.WTVFile;
break;
default:
itemType = DropItemType.None;
break;
}
canHandleDropData = (itemType != DropItemType.None);
}
if (canHandleDropData)
e.Effect = DragDropEffects.Copy;
}
Get the contents of the dragged file
public XmlDocument GetXmlDocument(DragEventArgs dragEventArgs)
{
var doc = new XmlDocument();
//Get content of outlook file not saved on disk
var rawContent = dragEventArgs.Data.GetData("FileContents");
if (rawContent == null)
{
//if null then it is a saved file and I can read its content by loading file name
var xmlString = File.ReadAllText(fileName);
doc.LoadXml(xmlString);
}
else
{
//outlook file content
var xmlString = rawContent as MemoryStream;
doc.Load(xmlString);
}
return doc;
}
source to share
This is the code I am using that converts files from Windows Explorer or attachments from Appearance to Memory Stream. (ms is the public memory stream variable in the form). I'm sure you can use the same logic to convert it to a string reader.
Private Sub ubFilepath_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ubFilepath.DragDrop
Try
If e.Data.GetDataPresent(DataFormats.Text) Then
Me.ubFilepath.Text = e.Data.GetData("Text")
ElseIf e.Data.GetDataPresent(DataFormats.FileDrop) Then
Dim fileNames() As String
Dim MyFilename As String
fileNames = DirectCast(e.Data.GetData(DataFormats.FileDrop), String())
MyFilename = fileNames(0)
Me.ubFilepath.Text = MyFilename
//RenPrivateItem is from outlook
ElseIf e.Data.GetDataPresent("RenPrivateItem") Then
Dim thestream As System.IO.MemoryStream = e.Data.GetData("FileGroupDescriptor")
Dim filename As New System.Text.StringBuilder("")
Dim fileGroupDescriptor(700) As Byte
Try
thestream.Read(fileGroupDescriptor, 0, 700)
Dim i As Integer = 76
While fileGroupDescriptor(i) <> 0
filename.Append(Convert.ToChar(fileGroupDescriptor(i)))
i += 1
End While
Me.ubFilepath.Text = "Outlook attachment_" + filename.ToString
ms = e.Data.GetData("FileContents", True)
Finally
If thestream IsNot Nothing Then thestream.Close()
End Try
End If
Catch ex As Exception
MessageBox.Show(ex.ToString, "Only files can be dragged into this box")
End Try
source to share