This is a migrated thread and some comments may be shown as answers.

Is it possible to move a pin on a map by click drag and drop?

3 Answers 511 Views
Map
This is a migrated thread and some comments may be shown as answers.
John
Top achievements
Rank 1
John asked on 21 Jun 2017, 07:10 PM
This is for moving a pin to a precise location on the map.  I saw the example of moving a pin and dropping it to a list box, but not to another location on the map, then save that new locations coordinates.  Thanks!

3 Answers, 1 is accepted

Sort by
0
Accepted
Hristo
Telerik team
answered on 23 Jun 2017, 02:10 PM
Hi John,

Thank you for writing.

You can follow a similar approach and handle the DragDrop event of the map instead of the list view. Please check my code snippet below: 
public partial class DragAndDropForm : RadForm
{
    public DragAndDropForm()
    {
        InitializeComponent();
 
        this.SetupProviders();
        this.SetupLayer();
        this.SetupLegend();
        this.SetupData();
 
        this.radMap1.AllowDrop = true;
 
        this.radMap1.MouseMove += RadMap1_MouseMove;
        this.radMap1.MouseUp += RadMap1_MouseUp;
        this.radMap1.DragEnter += RadMap1_DragEnter;
        this.radMap1.DragDrop += RadMap1_DragDrop;
    }
 
    private void RadMap1_DragDrop(object sender, DragEventArgs e)
    {
        MapPin pin = e.Data.GetData(typeof(MapPin)) as MapPin;
        if (pin != null)
        {
            Point p = this.radMap1.MapElement.PointFromScreen(new Point(e.X, e.Y));
            PointL pl = new PointL(p.X + this.radMap1.MapElement.ViewportInPixels.Location.X, p.Y + this.radMap1.MapElement.ViewportInPixels.Location.Y);
            PointG location = MapTileSystemHelper.PixelXYToLatLong(pl.X, pl.Y, this.radMap1.MapElement.ZoomLevel);
            pin.Location = new PointG(location.Latitude, location.Longitude);
        }
    }
 
    private void RadMap1_MouseMove(object sender, MouseEventArgs e)
    {
        if (!(e.Button == MouseButtons.Left))
        {
            return;
        }
 
        PointL point = new PointL(e.X - this.radMap1.MapElement.PanOffset.Width, e.Y - this.radMap1.MapElement.PanOffset.Height);
        MapPin pin = this.radMap1.Layers.HitTest(point) as MapPin;
 
        if (pin != null && this.radMap1.MapElement.EnablePanning)
        {
            this.radMap1.MapElement.EnablePanning = false;
        }
 
        if (pin == null && !this.radMap1.MapElement.EnablePanning)
        {
            this.radMap1.MapElement.EnablePanning = true;
        }
 
        if (pin != null)
        {
            ((RadMap)sender).DoDragDrop(pin, DragDropEffects.Move);
        }
    }
 
    private void RadMap1_DragEnter(object sender, DragEventArgs e)
    {
        MapPin pin = e.Data.GetData(typeof(MapPin)) as MapPin;
        e.Effect = pin == null ? DragDropEffects.None : DragDropEffects.Move;
    }
 
    private void RadMap1_MouseUp(object sender, MouseEventArgs e)
    {
        this.radMap1.MapElement.EnablePanning = true;
    }
 
    private void SetupProviders()
    {
        OpenStreetMapProvider osmProvider = new OpenStreetMapProvider();
        osmProvider.InitializationComplete += OsmProvider_InitializationComplete;
 
        this.radMap1.MapElement.Providers.Add(osmProvider);
    }
 
    private void OsmProvider_InitializationComplete(object sender, System.EventArgs e)
    {
        this.radMap1.Pan(new SizeL(-240, -440));
    }
 
    private void SetupLayer()
    {
        MapLayer pinsLayer = new MapLayer("Pins");
        MapLayer calloutLayer = new MapLayer("Callout");
        this.radMap1.Layers.Add(pinsLayer);
        this.radMap1.Layers.Add(calloutLayer);
    }
 
    private void SetupLegend()
    {
        this.radMap1.MapElement.LegendElement.TitleElement.Text = "Pins";
        this.radMap1.MapElement.LegendElement.SubtitleElement.Text = "Pin Layer";
        this.radMap1.MapElement.LegendElement.Orientation = Orientation.Horizontal;
 
        this.radMap1.MapElement.LegendElement.ItemStackElement.Children.Add(new MapLegendItemElement("Pins", Color.FromArgb(37, 160, 218)));
 
    }
 
    private void SetupData()
    {
        this.radMap1.BeginUpdate();
 
        using (StringReader reader = new StringReader(Properties.Resources.PhotoSpots))
        {
            string line;
 
            while ((line = reader.ReadLine()) != null)
            {
                string[] coordinates = line.Split(',');
                double latitude = double.Parse(coordinates[0], CultureInfo.InvariantCulture);
                double longitude = double.Parse(coordinates[1], CultureInfo.InvariantCulture);
 
                MapPin pin = new MapPin(new PointG(latitude, longitude));
                pin.Text = "Lat: " + coordinates[0] + " Long: " + coordinates[1];
                pin.BackColor = Color.FromArgb(37, 160, 218);
                this.radMap1.Layers["Pins"].Add(pin);
            }
        }
 
        this.radMap1.EndUpdate();
    }
}

I am also sending you a short video showing the result on my end.

I hope this helps. Should you have further questions please do not hesitate to write back.

Regards,
Hristo
Progress Telerik
Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Chris
Top achievements
Rank 1
answered on 22 Mar 2018, 01:43 PM
Hristo,

Is it possible for the pin to stay drawn while dragging? Currently the pin disappears during the drag, but we'd like it to remain throughout the process if possible. Can this be done? Thanks. 
0
Hristo
Telerik team
answered on 26 Mar 2018, 11:37 AM
Hello Chris,

Thank you for writing.

The required behavior can be achieved, however, it will require a different approach. The suggested solution in my previous post utilizes the native drag and drop support in Winforms. With the native OLE drag and drop the drag hint behavior can be achieved with some low-level native APIs. Additional information is available here: https://blogs.msdn.microsoft.com/adamroot/2008/02/19/shell-style-drag-and-drop-in-net-wpf-and-winforms/.

The alternative solution will not involve drag and drop at all. Instead, the actual movement of the pins will happen in the MouseMove and MouseUp events. Please check my code snippet below: 
public partial class CustomDragAndDropForm : RadForm
{
    public CustomDragAndDropForm()
    {
        InitializeComponent();
 
        this.SetupProviders();
        this.SetupLayer();
        this.SetupLegend();
        this.SetupData();
 
        this.radMap1.MouseMove += RadMap1_MouseMove;
        this.radMap1.MouseUp += RadMap1_MouseUp;
    }
 
    MapPin currentPin;
    long xOffset = 0;
    long YOffset = 0;
    private void RadMap1_MouseMove(object sender, MouseEventArgs e)
    {
        if (!(e.Button == MouseButtons.Left))
        {
            return;
        }
 
        PointL point = new PointL(e.X - this.radMap1.MapElement.PanOffset.Width, e.Y - this.radMap1.MapElement.PanOffset.Height);
        if (this.currentPin != null)
        {
            point.X += this.xOffset;
            point.Y += this.YOffset;
            PointG location = MapTileSystemHelper.PixelXYToLatLong(point.X, point.Y, this.radMap1.MapElement.ZoomLevel);
            this.currentPin.Location = new PointG(location.Latitude, location.Longitude);
        }
 
        MapPin pin = this.radMap1.Layers.HitTest(point) as MapPin;
        if (pin != null && this.currentPin == null && this.radMap1.MapElement.EnablePanning)
        {
            this.radMap1.MapElement.EnablePanning = false;
            pin.BackColor = Color.FromArgb(125, pin.BackColor.R, pin.BackColor.G, pin.BackColor.B);
 
            var pixelLocation = MapTileSystemHelper.LatLongToPixelXY(pin.Location, this.radMap1.MapElement.ZoomLevel);
            var drawRect = new RectangleL(pixelLocation.X - pin.Size.Width / 2, pixelLocation.Y - pin.Size.Height, pin.Size.Width, pin.Size.Height);
            this.xOffset = drawRect.X + drawRect.Width / 2 - point.X;
            this.YOffset = drawRect.Y + drawRect.Height - point.Y;
            this.currentPin = pin;
        }
    }
 
    private void RadMap1_MouseUp(object sender, MouseEventArgs e)
    {
        this.radMap1.MapElement.EnablePanning = true;
        if (this.currentPin != null)
        {
            this.currentPin.BackColor = Color.FromArgb(255, this.currentPin.BackColor.R, this.currentPin.BackColor.G, this.currentPin.BackColor.B);
            this.currentPin = null;
        }
    }
 
    private void SetupProviders()
    {
        OpenStreetMapProvider osmProvider = new OpenStreetMapProvider();
        osmProvider.InitializationComplete += OsmProvider_InitializationComplete;
 
        this.radMap1.MapElement.Providers.Add(osmProvider);
    }
 
    private void OsmProvider_InitializationComplete(object sender, System.EventArgs e)
    {
        this.radMap1.Pan(new SizeL(-240, -440));
    }
 
    private void SetupLayer()
    {
        MapLayer pinsLayer = new MapLayer("Pins");
        MapLayer calloutLayer = new MapLayer("Callout");
        this.radMap1.Layers.Add(pinsLayer);
        this.radMap1.Layers.Add(calloutLayer);
    }
 
    private void SetupLegend()
    {
        this.radMap1.MapElement.LegendElement.TitleElement.Text = "Pins";
        this.radMap1.MapElement.LegendElement.SubtitleElement.Text = "Pin Layer";
        this.radMap1.MapElement.LegendElement.Orientation = Orientation.Horizontal;
 
        this.radMap1.MapElement.LegendElement.ItemStackElement.Children.Add(new MapLegendItemElement("Pins", Color.FromArgb(37, 160, 218)));
 
    }
 
    private void SetupData()
    {
        this.radMap1.BeginUpdate();
 
        using (StringReader reader = new StringReader(Properties.Resources.PhotoSpots))
        {
            string line;
 
            while ((line = reader.ReadLine()) != null)
            {
                string[] coordinates = line.Split(',');
                double latitude = double.Parse(coordinates[0], CultureInfo.InvariantCulture);
                double longitude = double.Parse(coordinates[1], CultureInfo.InvariantCulture);
 
                MapPin pin = new MapPin(new PointG(latitude, longitude));
                pin.Text = "Lat: " + coordinates[0] + " Long: " + coordinates[1];
                pin.BackColor = Color.FromArgb(37, 160, 218);
                this.radMap1.Layers["Pins"].Add(pin);
            }
        }
 
        this.radMap1.EndUpdate();
    }
}

I am also attaching a short video showing the result on my end.

I hope this helps. Let me know if have other questions.

Regards,
Hristo
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
Tags
Map
Asked by
John
Top achievements
Rank 1
Answers by
Hristo
Telerik team
Chris
Top achievements
Rank 1
Share this question
or