Handing Map Events

 

Bing Maps WPF Control can respond to events that are raised when the user interacts with a map. You can intercept keyboard, mouse, and touch input events, and map navigation actions.

Note

Bing Maps WPF Control Map control currently does not have a mouse click event. If you want to intercept a single mouse click, use the MouseLeftButtonDown and MouseLeftButtonUp events.

Registering Map Events

For the map control to start listening or override the default implementation of an event, you must register that event and define a method handler. For example, if you want to track the latitude and longitude position of the map, as it animates between a source and target view, you can register the ViewChangeOnFrame event when a map called MyMap (assumed to be defined in the XAML design code) is loaded.

public TrackCurrentMapPosition
{
    InitializeComponent();
    MyMap.ViewChangeOnFrame += new EventHandler<MapEventArgs>(MyMap_ViewChangeOnFrame);
}
Public Sub New()
    InitializeComponent()
    AddHandler MapWithEvents.ViewChangeOnFrame, AddressOf MapWithEvents_ViewChangeOnFrame
End Sub

Assuming you have a TextBlock element named CurrentPosition defined in the XAML design code, you can track the current position of a map view while it is animating between locations. This code tracks the position, in latitude and longitude, of the northwest and southeast corners of the bounded map view.

void MyMap_ViewChangeOnFrame(object sender, MapEventArgs e)
{
    //Gets the map that raised this event
    Map map = (Map) sender;
    //Gets the bounded rectangle for the current frame
    LocationRect bounds = map.BoundingRectangle;
    //Update the current latitude and longitude
    CurrentPosition.Text += String.Format("Northwest: {0:F5}, Southeast: {1:F5} (Current)",
                bounds.Northwest, bounds.Southeast);
}
Private Sub MyMap_ViewChangeOnFrame(ByVal sender As Object, ByVal e As MapEventArgs)
    'Gets the map that raised this event
    Dim map As Map = CType(sender, Map)
    'Gets the bounded rectangle for the current frame
    Dim bounds As LocationRect = map.BoundingRectangle
    'Update the current latitude and longitude
    CurrentPosition.Text += String.Format("Northwest: {0:F5}, Southeast: {1:F5} (Current)", bounds.Northwest, bounds.Southeast)
End Sub

Example

The following example wires several map events and displays the number of times each event occurred while navigating the map. Each event handler calls the ShowEvent method, which updates the display panel’s counter for the raised event (passed in as a string parameter).

Map example that displays event counters

Map Event Counter Panel

<Window x:Class="WPFTestApplication.MapEvents"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:m="clr-namespace:Microsoft.Maps.MapControl.WPF;assembly=Microsoft.Maps.MapControl.WPF"
    Width="1024" Height="768">

    <Grid x:Name="LayoutRoot" Background="White">
        <m:Map x:Name="MapWithEvents" CredentialsProvider="Insert_Your_Bing_Maps_Key" 
               Mode="Road" 
               Center="37.806029,-122.407007" ZoomLevel="10"
               Grid.Column="0" Grid.Row="1" />
        <Border Background="Black" VerticalAlignment="Top" HorizontalAlignment="Right" Opacity="0.8" BorderBrush="White" BorderThickness="2" CornerRadius="5">
            <StackPanel x:Name="eventsPanel" IsHitTestVisible="False" Canvas.Left="0" Canvas.Top="0"/>
        </Border>
    </Grid>
</Window>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Collections.Generic;
using Microsoft.Maps.MapControl.WPF;

namespace WPFTestApplication
{
    public partial class MapEvents : Window
    {

        // A collection of key/value pairs containing the event name 
        // and the text block to display the event to.
        Dictionary<string, TextBlock> eventBlocks = new Dictionary<string, TextBlock>();
        // A collection of key/value pairs containing the event name  
        // and the number of times the event fired.
        Dictionary<string, int> eventCount = new Dictionary<string, int>();

        public MapEvents()
        {
            InitializeComponent();
            //Set focus on map
            MapWithEvents.Focus();

            // Fires every animated frame from one location to another.
            MapWithEvents.ViewChangeOnFrame += 
                new EventHandler<MapEventArgs>(MapWithEvents_ViewChangeOnFrame);
            // Fires when the map view location has changed.
            MapWithEvents.TargetViewChanged += 
                new EventHandler<MapEventArgs>(MapWithEvents_TargetViewChanged);
            // Fires when the map view starts to move to its new target view.
            MapWithEvents.ViewChangeStart += 
                new EventHandler<MapEventArgs>(MapWithEvents_ViewChangeStart);
            // Fires when the map view has reached its new target view.
            MapWithEvents.ViewChangeEnd += 
                new EventHandler<MapEventArgs>(MapWithEvents_ViewChangeEnd);
            // Fires when a different mode button on the navigation bar is selected.
            MapWithEvents.ModeChanged += 
                new EventHandler<MapEventArgs>(MapWithEvents_ModeChanged);
            // Fires when the mouse is double clicked
            MapWithEvents.MouseDoubleClick += 
                new MouseButtonEventHandler(MapWithEvents_MouseDoubleClick);
            // Fires when the mouse wheel is used to scroll the map
            MapWithEvents.MouseWheel +=
                new MouseWheelEventHandler(MapWithEvents_MouseWheel);
            // Fires when the left mouse button is depressed
            MapWithEvents.MouseLeftButtonDown +=
                new MouseButtonEventHandler(MapWithEvents_MouseLeftButtonDown);
            // Fires when the left mouse button is released
            MapWithEvents.MouseLeftButtonUp +=
                new MouseButtonEventHandler(MapWithEvents_MouseLeftButtonUp);
        }

        void MapWithEvents_MouseLeftButtonUp(object sender, MouseEventArgs e)
        {
            // Updates the count of single mouse clicks.
            ShowEvent("MapWithEvents_MouseLeftButtonUp");
        }

        void MapWithEvents_MouseWheel(object sender, MouseEventArgs e)
        {
            // Updates the count of mouse drag boxes created.
            ShowEvent("MapWithEvents_MouseWheel");
        }

        void MapWithEvents_MouseLeftButtonDown(object sender, MouseEventArgs e)
        {
            // Updates the count of mouse pans.
            ShowEvent("MapWithEvents_MouseLeftButtonDown");
        }

        void MapWithEvents_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            // Updates the count of mouse double clicks.
            ShowEvent("MapWithEvents_MouseDoubleClick");
        }

        void MapWithEvents_ViewChangeEnd(object sender, MapEventArgs e)
        {
            //Updates the number of times the map view has changed.
            ShowEvent("ViewChangeEnd");
        }

        void MapWithEvents_ViewChangeStart(object sender, MapEventArgs e)
        {
            //Updates the number of times the map view started changing.
            ShowEvent("ViewChangeStart");
        }

        void MapWithEvents_ViewChangeOnFrame(object sender, MapEventArgs e)
        {
            // Updates the number of times a map view has changed 
            // during an animation from one location to another.
            ShowEvent("ViewChangeOnFrame");
        }
        void MapWithEvents_TargetViewChanged(object sender, MapEventArgs e)
        {
            // Updates the number of map view changes that occured during
            // a zoom or pan.
            ShowEvent("TargetViewChange");
        }

        void MapWithEvents_ModeChanged(object sender, MapEventArgs e)
        {
            // Updates the number of times the map mode changed.
            ShowEvent("ModeChanged");
        }

        void ShowEvent(string eventName)
        {
            // Updates the display box showing the number of times 
            // the wired events occured.
            if (!eventBlocks.ContainsKey(eventName))
            {
                TextBlock tb = new TextBlock();
                tb.Foreground = new SolidColorBrush(
                    Color.FromArgb(255, 128, 255, 128));
                tb.Margin = new Thickness(5);
                eventBlocks.Add(eventName, tb);
                eventCount.Add(eventName, 0);
                eventsPanel.Children.Add(tb);
            }

            eventCount[eventName]++;
            eventBlocks[eventName].Text = String.Format(
                "{0}: [{1} times] {2} (HH:mm:ss:ffff)",
                eventName, eventCount[eventName].ToString(), DateTime.Now.ToString());
        }

    }
}
Imports System
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Input
Imports System.Windows.Media
Imports System.Collections.Generic
Imports Microsoft.Maps.MapControl.WPF

Namespace WPFTestApplication
    Partial Public Class MapEvents
        Inherits Window

        ' A collection of key/value pairs containing the event name 
        ' and the text block to display the event to.
        Private eventBlocks As New Dictionary(Of String, TextBlock)()
        ' A collection of key/value pairs containing the event name  
        ' and the number of times the event fired.
        Private eventCount As New Dictionary(Of String, Integer)()

        Public Sub New()
            InitializeComponent()

            ' Set focus on map
            MapWithEvents.Focus()

            ' Fires every animated frame from one location to another.
            AddHandler MapWithEvents.ViewChangeOnFrame, AddressOf MapWithEvents_ViewChangeOnFrame
            ' Fires when the map view location has changed.
            AddHandler MapWithEvents.TargetViewChanged, AddressOf MapWithEvents_TargetViewChanged
            ' Fires when the map view starts to move to its new target view.
            AddHandler MapWithEvents.ViewChangeStart, AddressOf MapWithEvents_ViewChangeStart
            ' Fires when the map view has reached its new target view.
            AddHandler MapWithEvents.ViewChangeEnd, AddressOf MapWithEvents_ViewChangeEnd
            ' Fires when a different mode button on the navigation bar is selected.
            AddHandler MapWithEvents.ModeChanged, AddressOf MapWithEvents_ModeChanged
            ' Fires when the mouse is double clicked
            AddHandler MapWithEvents.MouseDoubleClick, AddressOf MapWithEvents_MouseDoubleClick
            ' Fires when the mouse wheel is used to scroll the map
            AddHandler MapWithEvents.MouseWheel, AddressOf MapWithEvents_MouseWheel
            ' Fires when the left mouse button is depressed
            AddHandler MapWithEvents.MouseLeftButtonDown, AddressOf MapWithEvents_MouseLeftButtonDown
            ' Fires when the left mouse button is released
            AddHandler MapWithEvents.MouseLeftButtonUp, AddressOf MapWithEvents_MouseLeftButtonUp
        End Sub

        Private Sub MapWithEvents_MouseLeftButtonUp(ByVal sender As Object, ByVal e As MouseEventArgs)
            ' Updates the count of single mouse clicks.
            ShowEvent("MapWithEvents_MouseLeftButtonUp")
        End Sub


        Private Sub MapWithEvents_MouseWheel(ByVal sender As Object, ByVal e As MouseEventArgs)
            ' Updates the count of mouse drag boxes created.
            ShowEvent("MapWithEvents_MouseWheel")
        End Sub

        Private Sub MapWithEvents_MouseLeftButtonDown(ByVal sender As Object, ByVal e As MouseEventArgs)
            ' Updates the count of mouse pans.
            ShowEvent("MapWithEvents_MouseLeftButtonDown")
        End Sub

        Private Sub MapWithEvents_MouseDoubleClick(ByVal sender As Object, ByVal e As MouseEventArgs)
            ' Updates the count of mouse double clicks.
            ShowEvent("MapWithEvents_MouseDoubleClick")
        End Sub

        Private Sub MapWithEvents_ViewChangeEnd(ByVal sender As Object, ByVal e As MapEventArgs)
            'Updates the number of times the map view has changed.
            ShowEvent("ViewChangeEnd")
        End Sub

        Private Sub MapWithEvents_ViewChangeStart(ByVal sender As Object, ByVal e As MapEventArgs)
            'Updates the number of times the map view started changing.
            ShowEvent("ViewChangeStart")
        End Sub

        Private Sub MapWithEvents_ViewChangeOnFrame(ByVal sender As Object, ByVal e As MapEventArgs)
            ' Updates the number of times a map view has changed 
            ' during an animation from one location to another.
            ShowEvent("ViewChangeOnFrame")
        End Sub
        Private Sub MapWithEvents_TargetViewChanged(ByVal sender As Object, ByVal e As MapEventArgs)
            ' Updates the number of map view changes that occured during
            ' a zoom or pan.
            ShowEvent("TargetViewChange")
        End Sub

        Private Sub MapWithEvents_ModeChanged(ByVal sender As Object, ByVal e As MapEventArgs)
            ' Updates the number of times the map mode changed.
            ShowEvent("ModeChanged")
        End Sub

        Private Sub ShowEvent(ByVal eventName As String)
            ' Updates the display box showing the number of times 
            ' the wired events occured.
            If Not eventBlocks.ContainsKey(eventName) Then
                Dim tb As New TextBlock()
                tb.Foreground = New SolidColorBrush(Color.FromArgb(255, 128, 255, 128))
                tb.Margin = New Thickness(5)
                eventBlocks.Add(eventName, tb)
                eventCount.Add(eventName, 0)
                eventsPanel.Children.Add(tb)
            End If

            eventCount(eventName) += 1
            eventBlocks(eventName).Text = String.Format("{0}: [{1} times] {2} (HH:mm:ss:ffff)", eventName, eventCount(eventName).ToString(), Date.Now.ToString())
        End Sub

    End Class
End Namespace

Overriding Events

You can create custom behavior in response to a common event such as a mouse double-click by disabling the default event handler and providing custom code. The following example shows how to define custom behavior when the user double-clicks the map.

In the following XAML example, the MouseDoubleClick event handler is defined as the MapWithPushpins_MouseDoubleClick method.

<Grid x:Name="LayoutRoot" Background="White" >
    <m:Map x:Name="myMap"
           Center="37.1481402218342,-119.644248783588"
           ZoomLevel="6"
           MouseDoubleClick="MapWithPushpins_MouseDoubleClick"
           CredentialsProvider="Insert_Your_Bing_Maps_Key" 
           /> 
</Grid>

In the code-behind, the MapWithPushpins_MouseDoubleClick method disables the default mouse double-click action by setting the Handled property of the event arguments object to true. The method then proceeds to define custom behavior for the mouse double-click event.

private void MapWithPushpins_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
    // Disables the default mouse double-click action.
    e.Handled = true;

    // Determin the location to place the pushpin at on the map.

    //Get the mouse click coordinates
    Point mousePosition = e.GetPosition(this);
    //Convert the mouse coordinates to a locatoin on the map
    Location pinLocation = myMap.ViewportPointToLocation(mousePosition);

    // The pushpin to add to the map.
    Pushpin pin = new Pushpin();
    pin.Location = pinLocation;

    // Adds the pushpin to the map.
    myMap.Children.Add(pin);
}
Private Sub MapWithPushpins_MouseDoubleClick(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
    ' Disables the default mouse double-click action.
    e.Handled = True

    ' Determin the location to place the pushpin at on the map.

    'Get the mouse click coordinates
    Dim mousePosition As Point = e.GetPosition(Me)
    'Convert the mouse coordinates to a locatoin on the map
    Dim pinLocation As Location = myMap.ViewportPointToLocation(mousePosition)

    ' The pushpin to add to the map.
    Dim pin As New Pushpin()
    pin.Location = pinLocation

    ' Adds the pushpin to the map.
    myMap.Children.Add(pin)
End Sub