none
How to drag pushpin on Bing Map WPF?

    Question

  • Hi everyone, I am a newbie in Bing Map WPF. I just looked at this link http://pietschsoft.com/post/2010/05/30/Draggable-Pushpins-using-Bing-Maps-Silverlight-Control about draggable pushpin and tried to implement it but I couldn't do it. I had problem with the line: var parentMap = parentLayer.ParentMap . There is no ParentMap for parentLayer in WPF Bing Map. Also, parentMap doesn't have MousePan. I tried to re-edit it but it didn't work. Here is my code:

    XAML:

    <Grid x:Name="root">       
            <m:Map x:Name="MainMap" CredentialsProvider="your Bing map key" Center="30,-102" ZoomLevel="12"
                    PreviewTouchDown="MapWithPushpins_TouchDown"                
                        Mode="Road">
    
            </m:Map>
    </Grid>

    C#:

    public class DraggablePushpin : Microsoft.Maps.MapControl.WPF.Pushpin { private bool isDragging = false; MouseButtonEventHandler ParentMapMousePanHandler; MouseButtonEventHandler ParentMapMouseLeftButtonUpHandler; MouseEventHandler ParentMapMouseMoveHandler; protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) { // Check if the Map Event Handlers have been created/attached to the Map // If not, then attach them. This is done in the "Pushpin.OnMouseLeftButtonDown" // event because we don't know when the Pushpin is added to a Map or MapLayer, but // we do konw that when this event is fired the Pushpin will already have been added. var parentLayer = this.Parent as MapLayer; if (parentLayer != null) { //var parentMap = parentLayer.Tag as Map; var parentMap = parentLayer.Parent as Map; if (parentMap != null) { if (this.ParentMapMousePanHandler == null) { this.ParentMapMousePanHandler = new MouseButtonEventHandler(ParentMap_MousePan); parentMap.MouseDown += this.ParentMapMousePanHandler; } if (this.ParentMapMouseLeftButtonUpHandler == null) { this.ParentMapMouseLeftButtonUpHandler = new MouseButtonEventHandler(ParentMap_MouseLeftButtonUp); parentMap.MouseUp += this.ParentMapMouseLeftButtonUpHandler; } if (this.ParentMapMouseMoveHandler == null) { this.ParentMapMouseMoveHandler = new MouseEventHandler(ParentMap_MouseMove); parentMap.MouseMove += this.ParentMapMouseMoveHandler; } } } // Enable Dragging this.isDragging = true; base.OnMouseLeftButtonDown(e); } #region "Mouse Event Handler Methods" void ParentMap_MousePan(object sender, MouseEventArgs e) { // If the Pushpin is being dragged, specify that the Map's MousePan // event is handled. This is to suppress the Panning of the Map that // is done when the mouse drags the map. if (this.isDragging) { e.Handled = true; } } void ParentMap_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { // Left Mouse Button released, stop dragging the Pushpin this.isDragging = false; } void ParentMap_MouseMove(object sender, MouseEventArgs e) { var map = sender as Microsoft.Maps.MapControl.WPF.Map; // Check if the user is currently dragging the Pushpin if (this.isDragging) { // If so, the Move the Pushpin to where the Mouse is. var mouseMapPosition = e.GetPosition(map); var mouseGeocode = map.ViewportPointToLocation(mouseMapPosition); this.Location = mouseGeocode; } } #endregion }

    public partial class SurfaceWindow1 : SurfaceWindow
        {
            /// <summary>
            /// Default constructor.
            /// </summary>
            public SurfaceWindow1()
            {
                InitializeComponent();

                // Add handlers for window availability events
                AddWindowAvailabilityHandlers();
               
                MainMap.UseInertia = true;

                // The default animation level: navigate between different map locations.
                MainMap.AnimationLevel = AnimationLevel.Full;          

                MainMap.Focus();         
            }

    private void MapWithPushpins_TouchDown(object sender, TouchEventArgs e) { if (e.TouchDevice.GetTagData().Value == 1) { // Disables the default touch down behavior. e.Handled = true; // Determine the location to place the pushpin at on the map. //Get the touch down coordinates TouchPoint touchPosition = e.GetTouchPoint(this); //Convert the mouse coordinates to a location on the map Location pinLocation = MainMap.ViewportPointToLocation(touchPosition.Position); MapLayer mapLayer = new MapLayer(); DraggablePushpin myPushPin = new DraggablePushpin(); mapLayer.AddChild(myPushPin, pinLocation, PositionOrigin.Center); MainMap.Children.Add(mapLayer); } }

                                                                           

    Could you help me to solve this issue? Thanks in advance


                                           
    Tuesday, September 03, 2013 8:57 PM

Answers

  • You will need to pass a reference of the map control to the pushpin when creating it as it is not possible to get access to it use this parent in the WPF control. Try creating a constructor like this:

    private Map _map;
    
    public DraggablePushpin (Map map){
    	_map = map;
    }

    Instead of using mouse pan you will have to use the mouse move event. Or possibly using the view change events to disable the change

    http://rbrundritt.wordpress.com

    Friday, September 06, 2013 12:49 PM
    Owner
  • I've gone through and put together a sample. Here is the Draggable pushpin class I created:

    using Microsoft.Maps.MapControl.WPF;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Input;
    
    namespace DraggablePushpin
    {
        public class DraggablePin : Pushpin
        {
            private Map _map;
            private bool isDragging = false;
            Location _center;
    
            public DraggablePin(Map map)
            {
                _map = map;
            }
    
            protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
            {
                if (_map != null)
                {
                    _center = _map.Center;
    
                    _map.ViewChangeOnFrame += _map_ViewChangeOnFrame;
                    _map.MouseUp += ParentMap_MouseLeftButtonUp;
                    _map.MouseMove += ParentMap_MouseMove;
                }
    
                // Enable Dragging
                this.isDragging = true;
    
                base.OnMouseLeftButtonDown(e);
            }
    
            void _map_ViewChangeOnFrame(object sender, MapEventArgs e)
            {
                if (isDragging)
                {
                    _map.Center = _center;
                }
            }
    
            #region "Mouse Event Handler Methods"
    
            void ParentMap_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
            {
                // Left Mouse Button released, stop dragging the Pushpin
                if (_map != null)
                {
                    _map.ViewChangeOnFrame -= _map_ViewChangeOnFrame;
                    _map.MouseUp -= ParentMap_MouseLeftButtonUp;
                    _map.MouseMove -= ParentMap_MouseMove;
                }
    
                this.isDragging = false;
            }
    
            void ParentMap_MouseMove(object sender, MouseEventArgs e)
            {
                var map = sender as Microsoft.Maps.MapControl.WPF.Map;
                // Check if the user is currently dragging the Pushpin
                if (this.isDragging)
                {
                    // If so, the Move the Pushpin to where the Mouse is.
                    var mouseMapPosition = e.GetPosition(map);
                    var mouseGeocode = map.ViewportPointToLocation(mouseMapPosition);
                    this.Location = mouseGeocode;
                }
            }
            #endregion
        }
    }
    

    Here is how I implemented it:

    DraggablePin pin = new DraggablePin(MyMap)
    {
        Location = MyMap.Center
    };
    
    MyMap.Children.Add(pin);


    http://rbrundritt.wordpress.com

    Tuesday, September 10, 2013 2:50 PM
    Owner
  • I have uploaded the sample to MSDN here: http://code.msdn.microsoft.com/Draggable-Pushpins-in-Bing-48cb2683

    http://rbrundritt.wordpress.com

    Tuesday, September 10, 2013 4:08 PM
    Owner
  • Try adding the following touch move event to my original sample:

    void _map_TouchMove(object sender, TouchEventArgs e)
    {
        var map = sender as Microsoft.Maps.MapControl.WPF.Map;
        // Check if the user is currently dragging the Pushpin
        if (this.isDragging)
        {
            // If so, the Move the Pushpin to where the Mouse is.
            var mouseMapPosition = e.GetTouchPoint(map);
            var mouseGeocode = map.ViewportPointToLocation(mouseMapPosition.Position);
            this.Location = mouseGeocode;
        }
    }


    http://rbrundritt.wordpress.com

    • Marked as answer by Faro Luce Wednesday, September 11, 2013 3:37 PM
    Wednesday, September 11, 2013 8:07 AM
    Owner

All replies

  • You will need to pass a reference of the map control to the pushpin when creating it as it is not possible to get access to it use this parent in the WPF control. Try creating a constructor like this:

    private Map _map;
    
    public DraggablePushpin (Map map){
    	_map = map;
    }

    Instead of using mouse pan you will have to use the mouse move event. Or possibly using the view change events to disable the change

    http://rbrundritt.wordpress.com

    Friday, September 06, 2013 12:49 PM
    Owner
  • I still can't get it. Can you explain more where I should add your code? Is this the place where I should place your code?

    public partial class SurfaceWindow1 : SurfaceWindow { private Map _map; public void DraggablePushpin (Map map) { _map = map; } public SurfaceWindow1() { InitializeComponent(); MainMap.UseInertia = true; // Displays the current latitude and longitude as the map animates. MainMap.ViewChangeOnFrame += new EventHandler<MapEventArgs>(MainMap_ViewChangeOnFrame); // The default animation level: navigate between different map locations. MainMap.AnimationLevel = AnimationLevel.Full; } }

    private void MapWithPushpins_TouchDown(object sender, TouchEventArgs e)
            {
                if (e.TouchDevice.GetTagData().Value == 1)
                {
                    // Disables the default touch down behavior.
                    e.Handled = true;
    
                    // Determine the location to place the pushpin at on the map.
    
                    //Get the touch down coordinates
                    TouchPoint touchPosition = e.GetTouchPoint(this);
                    //Convert the mouse coordinates to a location on the map
                    Location pinLocation = MainMap.ViewportPointToLocation(touchPosition.Position);
                    MapLayer mapLayer = new MapLayer();
    
                    DraggablePushpin myPushPin = new DraggablePushpin();
    
                    mapLayer.AddChild(myPushPin, pinLocation, PositionOrigin.Center);
                    MainMap.Children.Add(mapLayer);
                }
            }

    I use mouse move for parentMap.MouseMove, mouse pan for parentMap.MouseDown and there is no success.  Do you have any idea? Thanks.


    • Edited by Faro Luce Monday, September 09, 2013 5:28 PM re-edit
    Monday, September 09, 2013 5:27 PM
  • I've gone through and put together a sample. Here is the Draggable pushpin class I created:

    using Microsoft.Maps.MapControl.WPF;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Input;
    
    namespace DraggablePushpin
    {
        public class DraggablePin : Pushpin
        {
            private Map _map;
            private bool isDragging = false;
            Location _center;
    
            public DraggablePin(Map map)
            {
                _map = map;
            }
    
            protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
            {
                if (_map != null)
                {
                    _center = _map.Center;
    
                    _map.ViewChangeOnFrame += _map_ViewChangeOnFrame;
                    _map.MouseUp += ParentMap_MouseLeftButtonUp;
                    _map.MouseMove += ParentMap_MouseMove;
                }
    
                // Enable Dragging
                this.isDragging = true;
    
                base.OnMouseLeftButtonDown(e);
            }
    
            void _map_ViewChangeOnFrame(object sender, MapEventArgs e)
            {
                if (isDragging)
                {
                    _map.Center = _center;
                }
            }
    
            #region "Mouse Event Handler Methods"
    
            void ParentMap_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
            {
                // Left Mouse Button released, stop dragging the Pushpin
                if (_map != null)
                {
                    _map.ViewChangeOnFrame -= _map_ViewChangeOnFrame;
                    _map.MouseUp -= ParentMap_MouseLeftButtonUp;
                    _map.MouseMove -= ParentMap_MouseMove;
                }
    
                this.isDragging = false;
            }
    
            void ParentMap_MouseMove(object sender, MouseEventArgs e)
            {
                var map = sender as Microsoft.Maps.MapControl.WPF.Map;
                // Check if the user is currently dragging the Pushpin
                if (this.isDragging)
                {
                    // If so, the Move the Pushpin to where the Mouse is.
                    var mouseMapPosition = e.GetPosition(map);
                    var mouseGeocode = map.ViewportPointToLocation(mouseMapPosition);
                    this.Location = mouseGeocode;
                }
            }
            #endregion
        }
    }
    

    Here is how I implemented it:

    DraggablePin pin = new DraggablePin(MyMap)
    {
        Location = MyMap.Center
    };
    
    MyMap.Children.Add(pin);


    http://rbrundritt.wordpress.com

    Tuesday, September 10, 2013 2:50 PM
    Owner
  • I have uploaded the sample to MSDN here: http://code.msdn.microsoft.com/Draggable-Pushpins-in-Bing-48cb2683

    http://rbrundritt.wordpress.com

    Tuesday, September 10, 2013 4:08 PM
    Owner
  • Hi Rick, thank you very much for your help. Your sample works great! However, when I modify your code to work with touching, it's really hard to move the pushpin. The position of the pushpin doesn't stick to the position of the finger. Do you know why it happened like that?

    Here is my code for touching:

    public class DraggablePin : Pushpin { private Map _map; private bool isDragging = false; Location _center; public DraggablePin(Map map) { _map = map; } protected override void OnTouchDown(TouchEventArgs e) { if (_map != null) { _center = _map.Center; _map.ViewChangeOnFrame += _map_ViewChangeOnFrame; _map.TouchUp += ParentMap_TouchUp; _map.TouchMove += ParentMap_TouchMove; } // Enable Dragging this.isDragging = true; base.OnTouchDown(e); } void _map_ViewChangeOnFrame(object sender, MapEventArgs e) { if (isDragging) { _map.Center = _center; } } #region "Touch Event Handler Methods" void ParentMap_TouchUp(object sender, TouchEventArgs e) { // Touch released, stop dragging the Pushpin if (_map != null) { _map.ViewChangeOnFrame -= _map_ViewChangeOnFrame; _map.TouchUp -= ParentMap_TouchUp; _map.TouchMove -= ParentMap_TouchMove; } this.isDragging = false; } void ParentMap_TouchMove(object sender, TouchEventArgs e) { var map = sender as Microsoft.Maps.MapControl.WPF.Map; // Check if the user is currently dragging the Pushpin if (this.isDragging) { // If so, move the Pushpin to where the finger is. // Get the location of the touch Point touchPosition = e.Device.GetPosition(this); var mouseGeocode = map.ViewportPointToLocation(touchPosition); this.Location = mouseGeocode; } } #endregion }

    private void MapWithPushpins_TouchDown(object sender, TouchEventArgs e)
    { if (e.TouchDevice.GetTagData().Value == 1) { // Disables the default touch down behavior. e.Handled = true; // Determine the location to place the pushpin at on the map. //Get the touch down coordinates TouchPoint touchPosition = e.GetTouchPoint(this); //Convert the mouse coordinates to a location on the map Location pinLocation = MainMap.ViewportPointToLocation(touchPosition.Position); MapLayer mapLayer = new MapLayer(); DraggablePin myPushPin = new DraggablePin(MainMap); //myPushPin.SourceUpdated += new BitmapImage(new Uri("Images/police.jpg", UriKind.Relative)); mapLayer.AddChild(myPushPin, pinLocation, PositionOrigin.Center); MainMap.Children.Add(mapLayer); } }



    Tuesday, September 10, 2013 6:43 PM
  • Try adding the following touch move event to my original sample:

    void _map_TouchMove(object sender, TouchEventArgs e)
    {
        var map = sender as Microsoft.Maps.MapControl.WPF.Map;
        // Check if the user is currently dragging the Pushpin
        if (this.isDragging)
        {
            // If so, the Move the Pushpin to where the Mouse is.
            var mouseMapPosition = e.GetTouchPoint(map);
            var mouseGeocode = map.ViewportPointToLocation(mouseMapPosition.Position);
            this.Location = mouseGeocode;
        }
    }


    http://rbrundritt.wordpress.com

    • Marked as answer by Faro Luce Wednesday, September 11, 2013 3:37 PM
    Wednesday, September 11, 2013 8:07 AM
    Owner
  • Thank you very much! It works!!! By the way, do you know how to change the image of the draggable pushpin? Thanks in advance.
    • Edited by Faro Luce Wednesday, September 11, 2013 4:06 PM re-edit
    Wednesday, September 11, 2013 3:38 PM
  • Hello Rick, do you know how I can change the default image of the draggable pushpin? Thanks a lot.
    Monday, September 16, 2013 6:28 PM
  • I got it. Don't worry about that.
    Monday, September 16, 2013 8:18 PM