1

I'm trying to make a tool with a feature can drag in raster layers from an mxd to the ListBox on a Windows Form and retrieve their file paths. So far I've found that the only format the layer can be converted to is "ESRI Layers" but I can't find any documentation on what to do from there. When I drag in one raster layer:

public ExporterForm()
{
    InitializeComponent();
    listBoxLayers.AllowDrop = true;
    listBoxLayers.DragEnter += new DragEventHandler(listBoxLayers_DragEnter);
    listBoxLayers.DragDrop += new DragEventHandler(listBoxLayers_DragDrop);
}

void listBoxLayers_DragEnter(object sender, DragEventArgs e)
{
    string[] formats = e.Data.GetFormats(); //returns string[].Length = 1
    DataFormats.Format esriLayersFormat = DataFormats.GetFormat(formats[0]);
    //esriLayersFormat.Name = "ESRI Layers"
    //esriLayersFormat.Id = 50082
    if (e.Data.GetDataPresent(DataFormats.FileDrop)) //tests false
        //only way I can think to retrieve the file info
}

I've tried using Activator.CreateInstance(e.Data.GetType()) but then I can't cast the object to any ESRI interfaces.

EDIT: I removed this line from listBoxLayers_DragEnter():

e.Data.SetData(esriLayerFormat);
2
  • Why are you calling SetData.. isn't that overwriting the data present with a string object? Commented Mar 13, 2017 at 23:36
  • I accidentally left that in there from when I was trying out different things, the problem originated before that. Commented Mar 14, 2017 at 13:33

1 Answer 1

1

There's a really good example from someone who's done this.. The main problem with your code is that you need to set e.Effect or the DragDrop method isn't fired:

void listBoxLayers_DragEnter(object sender, DragEventArgs e)
{
    DataFormats.Format esriLayerFormat = DataFormats.GetFormat("ESRI Layers");
    if (e.Data.GetDataPresent(esriLayerFormat.Name))
    {
        e.Effect = DragDropEffects.Copy;
    }
}

The next big step is to get the layers... because DragDrop is a Microsoft Windows event it needs to follow the Microsoft Windows rules which will copy the objects outside of the STA thread as a binary object that needs to be converted (deserialized) back into an Esri object on the tread to be useful in this context:

void listBoxLayers_DragDrop(object sender, DragEventArgs e)
{
    DataFormats.Format esriLayerFormat = DataFormats.GetFormat("ESRI Layers");
    Guid pUID = new Guid("{34C20002-4D3C-11D0-92D8-00805F7C28B0}"); // Esri Layer GUID
    if (e.Data.GetDataPresent(esriLayerFormat.Name))
    {
        System.IO.MemoryStream pDataStream = (System.IO.MemoryStream)e.Data.GetData(esriLayerFormat.Name, true);
        IMemoryBlobStreamVariant pMemBlobVar = new MemoryBlobStreamClass();
        pMemBlobVar.ImportFromVariant(pDataStream.ToArray());
        IStream pStream = (IStream)pMemBlobVar;
        IObjectStream pObjStream = new ObjectStreamClass();
        pObjStream.Stream = pStream;

        byte pv; // variables for the Microsoft method of the object stream
        uint cb = sizeof(int);
        uint pcbRead;
        pObjStream.RemoteRead(out pv, cb, out pcbRead); // https://msdn.microsoft.com/en-us/library/microsoft.sqlserver.dts.runtime.wrapper.istream.remoteread.aspx

        List<ILayer> pLayerList = new List<ILayer>();
        for (byte Cnt = 0; Cnt < pv; Cnt++)
        {
            // you could probably go straight to adding the converted object
            // like pLayerList.Add((ILayer)pObjStream.LoadObject(pUID, null));
            // to the list but showing it in 3 lines makes the process clearer I think
            object o = pObjStream.LoadObject(pUID, null);
            ILayer pThisLayer = (ILayer)o;
            pLayerList.Add(pThisLayer); // Add to the list of layers dropped
        }
    }

}

I have condensed the objects in the provided example to specifically ILayer objects. The DragDrop method will have a List object containing all the ILayer objects dropped onto the control, how you use this is up to you and the requirements of the rest of your program.. it might be safe to make the list global and reset/append by dragdrop then the data dropped will be available to other form events (like button click).

1
  • You're welcome. I learned a few things whist researching this as well, Commented Mar 15, 2017 at 21:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.