I know there are already several posts, but none quite what I need. I've got a custom dockpane which lists data from three different sources in three different treeviews. let's start with the vectors.
I can select my items and drop them on my vector_treeview which adds them with my custom method to my map.
at the start I have
vector_gdbTreeView.PreviewMouseLeftButtonDown += vector_DirectoryTreeView_PreviewMouseLeftButtonDown;
vector_gdbTreeView.PreviewMouseMove += vector_DirectoryTreeView_PreviewMouseMove;
vector_gdbTreeView.AllowDrop = true;
vector_gdbTreeView.Drop += vector_DirectoryTreeView_Drop;
and then the methods
private async Task AddVectorToMapMethod_string(string data_path)
{
...
}
private System.Windows.Point startPoint;
private void vector_DirectoryTreeView_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
startPoint = e.GetPosition(null);
}
private void vector_DirectoryTreeView_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
System.Windows.Point mousePos = e.GetPosition(null);
Vector diff = startPoint - mousePos;
if (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance)
{
System.Windows.MessageBox.Show(string.Join(Environment.NewLine, vector_selectedFileUrls), "Items");
// only handle one selected url
DataObject dragData = new DataObject("MyFormat", vector_selectedFileUrls.ToList()[0].ToString());
DragDrop.DoDragDrop(vector_gdbTreeView, dragData, DragDropEffects.Move);
}
}
}
private async void vector_DirectoryTreeView_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent("MyFormat"))
{
var droppedData = e.Data.GetData("MyFormat");
if (droppedData != null)
{
await QueuedTask.Run(async () =>
{
// Perform your drop operation here based on droppedData
await AddVectorToMapMethod_string(droppedData.ToString());
});
}
}
}
However I cannot figure out how to allow dropping it also in the table of content or on the map directly or on the entire surface of ArcGIS Pro. I thought I just need to set AllowDrop on those elements, but I cannot figure out how to reference these elements so that it allows AllowDrop... Can anyone please help me? thank you in advance 🙂
Hi,
To drop on content or map your data in clipboard must be in format: List<ClipboardItem>. Look at the DragAndDrop sample
Map or TOC doesn't understand custom data formats.
So if you want to drag and drop between your controls and map you need to use ArcGIS Pro format.
Thank you @GKmieliauskas - I saw that sample, but honestly I don't understand it (hardly any comments in the code and two or three similar drag&drop functions in the same example is not exactly beginnerfriendly...).
Anyway, can you tell me which part there is relevant for me? Since you pointed out that I need to use List<ClipboardItem> and the example seems to add feature classes to the map, I assume it's this:
private async Task<ObservableCollection<GDBBaseItem>> GetGDBItemsAsync()
{
var gdbItems = await QueuedTask.Run<ObservableCollection<GDBBaseItem>>(() =>
{
List<GDBBaseItem> lstGDBBaseItems = new List<GDBBaseItem>();
//Database becomes the root node
var path = Name;
var root = new DatabaseGDBItem { DBName = System.IO.Path.GetFileName(Name), Name = path, Path = path };
lstGDBBaseItems.Add(root);
// use the geodatabase to get all layers
var fGdbPath = new FileGeodatabaseConnectionPath(new Uri(Name, UriKind.Absolute));
using (var gdb = new Geodatabase(fGdbPath))
{
IReadOnlyList<Definition> fcList = gdb.GetDefinitions<FeatureClassDefinition>();
//Feature class
foreach (FeatureClassDefinition fcDef in fcList)
{
var fc = gdb.OpenDataset<FeatureClass>(fcDef.GetName());
var fd = fc.GetFeatureDataset();
var fc_path = (fd == null) ? path : path + @"\" + fd.GetName();
fc.Dispose();
fd?.Dispose();
switch (fcDef.GetShapeType())
{
case GeometryType.Point:
var pointfcItem = new PointFCGDBItem { Name = fcDef.GetName(), Path = fc_path };
root.Children.Add(pointfcItem);
break;
case GeometryType.Polyline:
var linefcItem = new LineFCGDBItem { Name = fcDef.GetName(), Path = fc_path };
root.Children.Add(linefcItem);
break;
case GeometryType.Polygon:
var polyfcItem = new PolygonFCGDBItem { Name = fcDef.GetName(), Path = fc_path };
root.Children.Add(polyfcItem);
break;
}
}
}
root.IsExpanded = true;
return new ObservableCollection<GDBBaseItem>(lstGDBBaseItems);
});
return gdbItems;
}
public void StartDrag(DragInfo dragInfo)
{
var sourceItem = dragInfo.SourceItem;
if (sourceItem == null)
return;
var gdbItem = dragInfo.SourceItem as GDBBaseItem;
if (gdbItem == null)
return;
if (gdbItem is DatabaseGDBItem)
return;//no dragging of the gdb
List<ClipboardItem> clip_items = new List<ClipboardItem>();
clip_items.Add(new ClipboardItem()
{
ItemInfoValue = gdbItem.GetItemInfoValue()
});
dragInfo.Data = clip_items;
dragInfo.Effects = DragDropEffects.Copy;
}
You must fill ClipboardItem from your own data like in method from DragAndDrop sample:
public virtual ItemInfoValue GetItemInfoValue()
{
var uri = _path + @"\" + _name;
var gdb_item = ItemFactory.Instance.Create(uri);
if (gdb_item == null)
{
MessageBox.Show($@"Unable to locate: {uri} - Feature datasets are not supported.");
}
return new ItemInfoValue()
{
name = gdb_item?.Name,
title = gdb_item?.Name,
catalogPath = gdb_item?.Path,
type = gdb_item?.Type,
typeID = gdb_item?.TypeID,
isContainer = "false"
};
}
Your dockpane must implement IDragSource interface (like in sample)