Working with Map Modes

This documentation is no longer available on MSDN, however it is available as a CHM download.

This topic describes how to work with the MapMode class to customize user interactions and map tile layers. When you create a new MapMode object, you are creating a 2D projection of the Earth. In the Bing Maps Silverlight Control, there are two main map modes that all other map modes are based on: FlatMapMode and MercatorMode. The FlatMapMode is a flattened representation of the Earth. MercatorMode is derived from FlatMapMode and represents a cylindrical projection of the Earth onto a 2D surface. The Mercator projection shows lines of latitude and longitude as perpendicular straight lines. The two standard map modes available in Bing Maps Silverlight Control are derived from MercatorMode and include RoadMode and AerialMode. Most often you derive from one of these classes so that you have the base tile layer available when defining the behavior of your new map mode. This is demonstrated in the Example section below.

Remove the Base Map Tile Layer

The simplest use of map mode customization is an empty map containing no base tile layer. Creating this empty representation is done by using the MercatorMode constructor. You can also specify your own tile source to overlay onto the map, but that is beyond the scope of this topic. When you instantiate your Map to use the MercatorMode, you can add tile overlays, shapes, images or videos to one or more MapLayer objects as discussed in other topics in the Developing with the Silverlight Map Control section. For example, you can add the following MapPolygon to the empty map.

using System.Windows.Controls;
using System.Windows.Media;

using Microsoft.Maps.MapControl;
using Microsoft.Maps.MapControl.Core;

namespace SilverlightApplication1
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();

            //Change the map mode to the base Mercator mode
            myMap.Mode = new MercatorMode();
            myMap.SetView(new Location(47.606115, -122.324495), 15);

            //Add new MapLayer containing the shape 
            MapLayer newLayer = new MapLayer();
            MapPolygon poly = new MapPolygon();

            //Define the polygon vertices
            LocationCollection boundingLocations = new LocationCollection();
            boundingLocations.Add(new Location(47.605,-122.323));
            boundingLocations.Add(new Location(47.607,-122.323));
            boundingLocations.Add(new Location(47.606115,-122.325));

            //Set the polygon properties
            poly.Locations = boundingLocations;
            poly.Fill = new SolidColorBrush(Colors.Green);
            poly.Stroke = new SolidColorBrush(Colors.Blue);
            poly.StrokeThickness = 4;
            newLayer.Children.Add(poly);

            //Add the layer containing the polygon to the map
            myMap.Children.Add(newLayer);
       }
    }
}
Imports Microsoft.Maps.MapControl
Imports Microsoft.Maps.MapControl.Core


Partial Public Class MainPage
    Inherits UserControl
    Public Sub New()
        InitializeComponent()

        'Change the map mode to the base Mercator mode
        MapTileOverlay.Mode = New MercatorMode()
        MapTileOverlay.SetView(New Location(47.606115, -122.324495), 15)

        'Add new MapLayer containing the shape 
        Dim newLayer As New MapLayer()
        Dim poly As New MapPolygon()

        'Define the polygon vertices
        Dim boundingLocations As New LocationCollection()
        boundingLocations.Add(New Location(47.605, -122.323))
        boundingLocations.Add(New Location(47.607, -122.323))
        boundingLocations.Add(New Location(47.606115, -122.325))

        'Set the polygon properties
        poly.Locations = boundingLocations
        poly.Fill = New SolidColorBrush(Colors.Green)
        poly.Stroke = New SolidColorBrush(Colors.Blue)
        poly.StrokeThickness = 4
        newLayer.Children.Add(poly)

        'Add the layer containing the polygon to the map
        MapTileOverlay.Children.Add(newLayer)
    End Sub
End Class

Ee681896.7a117699-3fd7-4118-932c-490cc742ea89(en-us,MSDN.10).jpg

Creating a Custom Map Mode

To define how users can interact with your map, you need to override methods and properties in your custom map mode implementation. Functionality that can be overridden includes restricting the map view, defining the zoom range, managing how keyboard and mouse events affect map navigation, and defining how a Location on the map and a Point on the screen correspond. For a full list of MapMode members, see the MapMode topic.

The following examples demonstrates creating a custom map mode based on the AerialMode class. This custom map mode constrains the viewable map and zoom level to the downtown Seattle area. The constrained map does not allow you to zoom or pan beyond the specified range values (validLatitudeRange, validLongitudeRange, and getZoomRange). This example overrides the GetZoomRange method to define the valid zoom range for the current map view. In this case you only want to allow zoom levels 14 to 21 in order to stay within the downtown Seattle area. The ConstrainView method is overridden in order to specify the bounding rectangle in which you are allowed to pan the map. Any attempt to pan the map outside this bounding rectangle sets the center of the map to the nearest boundary.

Note

GetZoomRange and ConstrainView execute every time the map view changes.

<UserControl x:Class="SilverlightTest1.CustomMapMode"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:m="clr-namespace:Microsoft.Maps.MapControl;assembly=Microsoft.Maps.MapControl"
    Width="1024" Height="768">
    <Grid x:Name="LayoutRoot" Background="White">
        <m:Map x:Name="MapCustomMode" CredentialsProvider="your key" >
        </m:Map>
    </Grid>
</UserControl>
    
using System.Windows.Controls;
using Microsoft.Maps.MapControl;

namespace SilverlightTest1
{
    public class SeattleMapMode : AerialMode
    {
        private Range<double> validLatitudeRange;
        private Range<double> validLongitudeRange;

        public SeattleMapMode()
        {
            // The latitude value range (From = bottom most latitude, To = top most latitude)
            validLatitudeRange = new Range<double>(47.58346, 47.62877);
            // The longitude value range (From = left most longitude, To = right most longitude)
            validLongitudeRange = new Range<double>(-122.36298, -122.28599);
        }

        // Restricts the map view.
        protected override Range<double> GetZoomRange(Location center)
        {
            // The allowable zoom levels - 14 to 21.
            return new Range<double>(14, 21);
        }

        
        // This method is called when the map view changes on Keyboard 
        // and Navigation Bar events.
        public override bool ConstrainView(Location center, ref double zoomLevel, ref double heading, ref double pitch)
        {
            bool isChanged = base.ConstrainView(center, ref zoomLevel, ref heading, ref pitch);

            double newLatitude = center.Latitude;
            double newLongitude = center.Longitude;

            // If the map view is outside the valid longitude range,
            // move the map back within range.
            if (center.Longitude > validLongitudeRange.To)
            {
                newLongitude = validLongitudeRange.To;
            }
            else if (center.Longitude < validLongitudeRange.From)
            {
                newLongitude = validLongitudeRange.From;
            }

            // If the map view is outside the valid latitude range,
            // move the map back within range.
            if (center.Latitude > validLatitudeRange.To)
            {
                newLatitude = validLatitudeRange.To;
            }
            else if (center.Latitude < validLatitudeRange.From)
            {
                newLatitude = validLatitudeRange.From;
            }

            // The new map view location.
            if (newLatitude != center.Latitude || newLongitude != center.Longitude)
            {
                center.Latitude = newLatitude;
                center.Longitude = newLongitude;
                isChanged = true;
            }

            // The new zoom level.
            Range<double> range = GetZoomRange(center);
            if (zoomLevel > range.To)
            {
                zoomLevel = range.To;
                isChanged = true;
            }
            else if (zoomLevel < range.From)
            {
                zoomLevel = range.From;
                isChanged = true;
            }

            return isChanged;
        }
    }

    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();

            // Sets the map to the custom map mode.
            MapCustomMode.Mode = new SeattleMapMode();
        }
    }
}
    

Imports Microsoft.Maps.MapControl


    Public Class SeattleMapMode
        Inherits AerialMode
        Private validLatitudeRange As Range(Of Double)
        Private validLongitudeRange As Range(Of Double)

        Public Sub New()
            ' The latitude value range (From = bottom most latitude, To = top most latitude)
            validLatitudeRange = New Range(Of Double)(47.58346, 47.62877)
            ' The longitude value range (From = left most longitude, To = right most longitude)
            validLongitudeRange = New Range(Of Double)(-122.36298, -122.28599)
        End Sub

        ' Restricts the map view.
        Protected Overrides Function GetZoomRange(ByVal center As Location) As Range(Of Double)
            ' The allowable zoom levels - 14 to 21.
            Return New Range(Of Double)(14, 21)
        End Function


        ' This method is called when the map view changes on Keyboard 
        ' and Navigation Bar events.
        Public Overrides Function ConstrainView(ByVal center As Location, ByRef zoomLevel As Double, _
                                                ByRef heading As Double, ByRef pitch As Double) As Boolean
            Dim isChanged = MyBase.ConstrainView(center, zoomLevel, heading, pitch)

            Dim newLatitude = center.Latitude
            Dim newLongitude = center.Longitude

            ' If the map view is outside the valid longitude range,
            ' move the map back within range.
            If center.Longitude > validLongitudeRange.To Then
                newLongitude = validLongitudeRange.To
            ElseIf center.Longitude < validLongitudeRange.From Then
                newLongitude = validLongitudeRange.From
            End If

            ' If the map view is outside the valid latitude range,
            ' move the map back within range.
            If center.Latitude > validLatitudeRange.To Then
                newLatitude = validLatitudeRange.To
            ElseIf center.Latitude < validLatitudeRange.From Then
                newLatitude = validLatitudeRange.From
            End If

            ' The new map view location.
            If newLatitude <> center.Latitude OrElse newLongitude <> center.Longitude Then
                center.Latitude = newLatitude
                center.Longitude = newLongitude
                isChanged = True
            End If

            ' The new zoom level.
            Dim range = GetZoomRange(center)
            If zoomLevel > range.To Then
                zoomLevel = range.To
                isChanged = True
            ElseIf zoomLevel < range.From Then
                zoomLevel = range.From
                isChanged = True
            End If

            Return isChanged
        End Function
    End Class

    Partial Public Class MainPage
        Inherits UserControl
        Public Sub New()
            InitializeComponent()

            ' Sets the map to the custom map mode.
            MapCustomMode.Mode = New SeattleMapMode()
        End Sub
    End Class

    
 

In the example above, the map navigation control is still available, so the user can still select the Road and Aerial map modes to navigate beyond the bounds that you have defined in the SeattleMapMode class. To prevent this, you can customize the navigation control so that the user cannot access these other modes. Your MainPage class code now looks like the code below.

 public partial class MainPage : UserControl
 {
     public MainPage()
     {
         InitializeComponent();

         // Sets the map to the custom map mode.
         MapCustomMode.Mode = new SeattleMapMode();

         MapCustomMode.MapForeground.TemplateApplied += new EventHandler(MapForeground_TemplateApplied);
         
     }

     void MapForeground_TemplateApplied(object sender, EventArgs e)
     {
         MapCustomMode.MapForeground.NavigationBar.TemplateApplied += new EventHandler(NavigationBar_TemplateApplied);
     }

     void NavigationBar_TemplateApplied(object sender, EventArgs e)
     {
         NavigationBar navControl = MapCustomMode.MapForeground.NavigationBar;

         navControl.HorizontalPanel.Children.Clear();
     }


}
 


Partial Public Class MainPage
    Inherits UserControl

    Public Sub New()
        InitializeComponent()

        ' Sets the map to the custom map mode.
        MapCustomMode.Mode = New SeattleMapMode()

        AddHandler MapCustomMode.MapForeground.TemplateApplied, AddressOf MapForeground_TemplateApplied
    End Sub

    Private Sub MapForeground_TemplateApplied()
        AddHandler MapCustomMode.MapForeground.NavigationBar.TemplateApplied, AddressOf NavigationBar_TemplateApplied
    End Sub

    Private Sub NavigationBar_TemplateApplied()
        Dim navControl = MapCustomMode.MapForeground.NavigationBar

        navControl.HorizontalPanel.Children.Clear()
    End Sub

End Class

 

See Also

Reference

MapMode
FlatMapMode
MercatorMode