ThinkGeo.com    |     Documentation    |     Premium Support

Possible Bug in Map_DragDrop Event?

 


Hi,
I'm using the latest RC of the Desktop and I'm trying to implement some functionality where a user can pick from a tool bar of images and drag them onto the map.  Then I capture the Map_DragDrop Event and add these to an inMemoryLayer and display them on the map.  
 
I sort of have it working but I ran into a problem, it seems that the screen coordinates passed into the Map_DragDrop event are the screen coordinates relative to the entire screen instead of the map control.  When I use the ExtenHelpler.ToWorldCoordinate method it doesn't work unless I put the upper left point of the map in the upper left corner of the screen.
 
Is this a bug?  I would expect the screen coordinates passed into the Map_DragDrop event would be relative to the Map Control. 
 
Some Prerequisites:
1.     I set the AllowDrop property on the Map to True.
2.     My Map Unit is set to DecimalDegrees.
 
Below is my code:
 
// This is the button on the tool bar that the user will drag onto the Map.
private void button3_MouseDown(object sender, MouseEventArgs e)
{
this.button3.DoDragDrop(this.button3, DragDropEffects.Move);
}
 
// Implement the Map_DragEnter event so the cursor shows correctly once the user enters the map area with the draggable item.
private void Map_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
 
// Here is where I implement the Map_DragDrop event to capture where the user dropped the item. I get the screen coordinates from the DragEventArgs, then convert them to world coordinates and add it to my existing InMemoryFeatureLayer.
        private void Map_DragDrop(object sender, DragEventArgs e)
        {
            LayerOverlay housesOverlay = (LayerOverlay)Map.Overlays["houseOverlay"];
            housesOverlay.Lock.EnterWriteLock();
            InMemoryFeatureLayer houses = (InMemoryFeatureLayer)housesOverlay.Layers["houses"];
            PointShape ps = ExtentHelper.ToWorldCoordinate(Map.CurrentExtent, new ScreenPointF(e.X, e.Y), Map.Width, Map.Height);
            Feature draggedFeature = new Feature(ps);
            houses.InternalFeatures.Add(draggedFeature);
            housesOverlay.Lock.ExitWriteLock();
            Map.Refresh();
        }
Thanks!

Clint, 


This is not a bug, this is just some magic thing happened in the DragDrop EventArgs e, the e.X, e.Y is the screen coordinate reference to the whole screen instead of the WinformsMap or the Forms holding the Map.
 
We also tests some other standards control just like the listbox etc, it follow the same rule.So just try the following codes in your Map_DragDorp event.
 

LayerOverlay housesOverlay = (LayerOverlay)winformsMap1.Overlays["houseOverlay"];
housesOverlay.Lock.EnterWriteLock();
try
{
   InMemoryFeatureLayer houses = (InMemoryFeatureLayer)housesOverlay.Layers["houses"];
   float relatedX = e.X - this.Location.X - winformsMap1.Location.X;
   float relatedY = e.Y - this.Location.Y - winformsMap1.Location.Y;
   PointShape ps = ExtentHelper.ToWorldCoordinate(winformsMap1.CurrentExtent, new ScreenPointF(relatedX, relatedY), winformsMap1.Width, winformsMap1.Height);
   Feature draggedFeature = new Feature(ps);
   houses.InternalFeatures.Add(draggedFeature);
}
finally
{
   housesOverlay.Lock.ExitWriteLock();
}
winformsMap1.Refresh(); 

 

Any more questions just let me know.
 
Thanks.
 
Yale


Yale, 



I am attempting to convert this functionality to the wpfMap control.  The issue I am having is that the DragEventArgs e does not contain an X/Y value.  I attempt to get the coordinates with the e.GetPosition(null); function but that is not working either.  The other issue is I can't get this.Location.X nor winformsMap1.Location.X since Location doesn't appear to be a valid object.  Is there a way to make this function work with WPF?


 
Point mousePos = e.GetPosition(null); 

LayerOverlay housesOverlay = (LayerOverlay)wpfMap.Overlays["houseOverlay"]; 
housesOverlay.Lock.EnterWriteLock(); 
try 

InMemoryFeatureLayer houses = (InMemoryFeatureLayer)housesOverlay.Layers["houses"]; 
//float relatedX = mousePos.X - this.Location.X - wpfMap.Location.X; 
//float relatedY = mousePos.Y - this.Location.Y - wpfMap.Location.Y; 
PointShape ps = ExtentHelper.ToWorldCoordinate(wpfMap.CurrentExtent, new ScreenPointF((float)mousePos.X, (float)mousePos.Y), 
(float)wpfMap.Width, (float)wpfMap.Height); 
//PointShape ps = ExtentHelper.ToWorldCoordinate(wpfMap.CurrentExtent, new ScreenPointF(relatedX, relatedY), 
//(float)wpfMap.Width, (float)wpfMap.Height); 
Feature draggedFeature = new Feature(ps); 
houses.InternalFeatures.Add(draggedFeature); 

finally 

housesOverlay.Lock.ExitWriteLock();

wpfMap.Refresh(); 


 



Jake, 
  
 I DONOT think in WPF we can do this effect, sorry for my bad understanding for this problem. Can you send me your sample code to recreate the problem? 
  
 Thanks. 
  
 Yale 


I will see if I can put together an example that can be sent, thanks for looking into it.  If you look and see it can't be done, let me know if you have any alternate possibilities.  What we are looking to do is populate a list of locations in a listbox that don't have gps data so users can drag them onto the map to populate the gps data.  So what we need is a way to get the unmapped shapes onto the map so the user can drag them to their correct location.  We were happy with the winforms drag and drop functionality, so would really like to mirror that into the WPF application.  I think all we are missing is the X,Y Location of the map, which I know is possible to get in WPF since MapClickWpfMapEventArgs e contains both Screen X,Y and World X,Y.


I will get the attachment put together for you to look at.



Yale,


    The attachment has a project that works***.  It will place the dropped item in the correct spot.  When using the function e.GetPosition() you are able to reference any item.  I am using e.GetPosition(this), where "this" is the parent window, which in this case is fine since the map control is located in the top left corner of the window.  If you have controls above or to the right of the mapcontrol, you just have to reference this.[mapcontrol].


 


***The project references some worldmapkit files along with some others, so it won't run correctly without changing some of the references to point to a valid map.  The functions that matter are


        private void Button_PreviewMouseMove(object sender, MouseEventArgs e)



        private void Button_PreviewMouseDown(object sender, MouseButtonEventArgs e)



        private void wpfMap_Drop(object sender, DragEventArgs e)



Jake,


Thanks for your post and demo, I appreciate it very much!
 
I found that the label in the demo cannot work correctly, so I fixed it in attachmentJ, besides, just want to let you know that I delete the attachment in your post because it contains some source code of WorldMapKit, sorry for that.
 
Thanks.
 
Any more questions feel free to let us know.
 
Yale

1082-MapKit.zip (12.3 KB)