Community Coding Contest 2010 - Looking for Input and Prizes

4. January 2010

Now that it's 2010, and over a year since the first Community Coding Contest came to an end, I'm thinking about running the contest again in 2010.

Last time it ran for 3 months and we had 6 really great entries. This time around I'm thinking that it may be better to accept entries for 6 months, and have the voting run for a full month. This will give much more time for entries to be submitted, and for people to work on their entries before submitting and/or voting begins.

These are just some initial thoughts, and I'm going to need input on everything from YOU (the community) before I can make a final decision as to when and how to run the contest again. I'd really appreciate if you could fill out the following survey and tell us what you think.

Community Coding Contest 2010 Pre-Contest Survey

Also, we will need some prizes donated before the contest will be able to go on. If you or your company are interested in donating prizes or monetary support (web hosting fees, mailing expenses, etc.) for the contest, please contact the contest directly here: http://communitycodingcontest.org/contact.aspx

You can view the official contest website here: http://communitycodingcontest.org

Thanks, and I look forward to hearing more about what everyone thinks!

asp.net, ASP.NET MVC, Bing Maps, C#, General, Silverlight, vb.net , , , ,

Prototype of OpenStreetMap Silverlight Control using DeepEarth and Bing Maps SDK

13. November 2009

I’ve decided to expand a little on using OpenStreetMap imagery with the new Bing Maps Silverlight Control in response to the following comment posted by John O’Brien on my previous “Display OpenStreetMap Imagery using Bing Maps Silverlight Control v1” post:

“Very close Chris but you will still need to enter a Bing Maps AppID.
If however you create your own map from MapCore and don't use the Bing Maps services then you don't need creditials”

Yes, it is true that by just displaying the OpenStreetMap imagery on the Bing Maps Silverlight Control using a custom TileSource you still need to provide the control a Bing Maps Key (App ID). However, what if you inherited from the “MapCore” base class (the same one that the Bing Maps “Map” object inherits) and built out a full OpenStreetMap Map control?

Custom “OpenStreetMap” Control

I built out a test “OpenStreetMap” object that inherits from “MapCore” that automatically sets the Map Mode to a “OpenStreetMapMode” object that loads up the OpenStreetMap imagery automatically. This was some simple code to write, basically just extending only a little bit on top of what I posted in the previous post.

Here’s the code for the “OpenStreetMap”, “OpenStreetMapMode” and “OpenStreetMapTileSource” objects:

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

namespace SilverlightApplication1
{
    public class OpenStreetMap : MapCore
    {
        public OpenStreetMap()
            : base()
        {
            this.Mode.SetView(new Location(), 2.0, 0.0, 0.0, false);
            this.Mode = new OpenStreetMapMode();
        }
    }

    public class OpenStreetMapMode : RoadMode
    {
        public OpenStreetMapMode()
            : base()
        {
            var tileLayer = (MapTileLayer)this.Content;
            tileLayer.TileSources.Clear();
            tileLayer.TileSources.Add(new OpenStreetMapTileSource());
        }
    }

    public class OpenStreetMapTileSource : TileSource
    {
        public OpenStreetMapTileSource()
            : base("http://tile.openstreetmap.org/{2}/{0}/{1}.png")
        {
        }

        public override System.Uri GetUri(int x, int y, int zoomLevel)
        {
            return new Uri(string.Format(this.UriFormat, x, y, zoomLevel));
        }
    }
}

 

And, here’s an example of using this new “OpenStreetMap” control:

<UserControl x:Class="SilverlightApplication1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:map="clr-namespace:Microsoft.Maps.MapControl;assembly=Microsoft.Maps.MapControl"
    xmlns:local="clr-namespace:SilverlightApplication1"
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
    <Grid x:Name="LayoutRoot">
        <local:OpenStreetMap Name="map">
            <local:OpenStreetMap.Children>
                <map:MapLayer>
                    <Image Source="BluePin.png" Opacity="0.8" Stretch="None" map:MapLayer.Position="42.16, -95"></Image>
                </map:MapLayer>
            </local:OpenStreetMap.Children>
        </local:OpenStreetMap>
    </Grid>
</UserControl>

 

What About Navigation Controls?

One side effect of creating this completely custom Map Control based off MapCore is that the other controls that the “Map” control includes automatically do not get displayed.

The “Map” control displays the “MapControlNavigationBar” control via the “MapForeground” object, however due to the MapForeground constructor that lets you tell it what MapBase object to attach to being marked “internal” is seems that it can’t be easily reused.

However, with a little help from the newest controls in developments within the DeepEarth project, you can fairly simply modify the Bing Maps Navigation control within the DeepEarth project to be used with the new “OpenStreetMap” control.

Here’s the code I worked up for a DeepEarth NavigationPanel for the “OpenStreetMap” control created earlier:

using System;
using System.Windows;
using DeepEarth.Client.BingMaps.Convertors;
using DeepEarth.Client.Common;
using GeoAPI.Geometries;
using GisSharpBlog.NetTopologySuite.Geometries;
using Microsoft.Maps.MapControl;
using Point = System.Windows.Point;
using Microsoft.Maps.MapControl.Core;

namespace NewDeepEarth.NavigationPanel
{
    public class NavigationPanel : DeepEarth.Client.Controls.NavigationPanel.NavigationPanel, IMapControl<MapCore>
    {
        private string mapName;

        public NavigationPanel()
        {
            Loaded += CoordinatePanel_Loaded;
        }

        public override double ZoomLevel
        {
            get
            {
                if (MapInstance != null)
                {
                    return MapInstance.ZoomLevel;
                }
                return 0;
            }
            set
            {
                if (MapInstance != null)
                {
                    MapInstance.ZoomLevel = value;
                }
            }
        }

        public override ICoordinate Center
        {
            get
            {
                if (MapInstance != null)
                {
                    return CoordinateConvertor.Convert(MapInstance.Center);
                }
                return new Coordinate(0, 0);
            }
            set
            {
                if (MapInstance != null)
                {
                    MapInstance.Center = CoordinateConvertor.ConvertBack(value);
                }
            }
        }

        #region IMapControl<MapCore> Members

        public string MapName
        {
            get { return mapName; }
            set
            {
                mapName = value;
                setMapInstance(MapName);
            }
        }

        public MapCore MapInstance { get; set; }

        public new void Dispose()
        {
            MapInstance = null;
            base.Dispose();
        }

        public override void PanMap(int deltaX, int deltaY)
        {
            if (MapInstance != null)
            {
                NewDeepEarth.Client.BingMaps.Utilities.Pan(deltaX, deltaY, MapInstance);
            }
        }

        #endregion

        private void CoordinatePanel_Loaded(object sender, RoutedEventArgs e)
        {
            setMapInstance(MapName);
        }

        private void setMapInstance(string mapname)
        {
            MapInstance = Utilities.FindVisualChildByName<MapCore>(Application.Current.RootVisual, mapname);
        }

    }
}

Also, hers a small utility method that I needed to modify slightly within the DeepEarth project to get the above NavigationPanel to work:

using Microsoft.Maps.MapControl.Core;
using Point = System.Windows.Point;

namespace NewDeepEarth.Client.BingMaps
{
    public static class Utilities
    {
        // Convert to accept Bing Maps "MapCore" instead of "Map" object
        public static void Pan(double deltaX, double deltaY, MapCore map) //Map map)
        {
            Point center = map.LocationToViewportPoint(map.Center);
            center.X = center.X + deltaX;
            center.Y = center.Y + deltaY;
            map.Center = map.ViewportPointToLocation(center);
        }
    }
}

 

Suggestion for the DeepEarth Preview Controls

One big suggestion I have for the DeepEarth projects new Preview Controls is to make the Bing Maps objects/libraries within the project use/accept “MapCore” or “MapBase” where ever it can instead of “Map”. This way as much of the DeepEarth code can be reused, without modification, when building a completely custom Map Control using the Bing Maps Silverlight SDK.

A perfect example of this are the modifications I needed to make to the NavigationPanel object and Utilities.Pan method posted above. By simply changing them from referencing/using “Map” to “MapCore” instead, they can not be used with any Map Control built using the Bing Maps Silverlight SDK.

Conclusion

Even though the above code works, it’s really just a prototype of what can be done using the current Preview controls within the DeepEarth project along with the new Bing Maps Silverlight Control. There is definitely some cool stuff to be done with both the Bing Maps Silverlight SDK and the DeepEarth project!

Anyway, here’s a download link to the full code of the project for the above code:

C#, Bing Maps, Silverlight , , , ,

Display OpenStreetMap Imagery using Bing Maps Silverlight Control v1

12. November 2009

BingMapsSilverlight_OpenStreetMap The Bing Maps Silverlight SDK documentation on MSDN contains an article on Adding Tile Overlays to the Map, that demonstrates how to overlay your own map imagery over top of the Bing Maps Imagery. However, what if you want to completely replace the Bing Maps Imagery with some other Imagery like the OpenStreeMap Imagery?

In the “Adding Tile Overlays to the Map” article it shows using a “LocationRectTileSource” to add the custom map imagery overlay. To implement the OpenStreetMap imagery you will need to create a simple class that inherits from “TileSource” since you wont be restricting the imagery to only a small portion of the map, but instead will be showing all the OpenStreetMap Imagery in place of the Bing Maps Imagery.

First, Hide the Bing Maps Imagery

Since we will be displaying the OpenStreetMap imagery instead of the Bing Maps Imagery, we want to prevent the Map control from loading/displaying the Bing Maps Imagery completely.

To do this, all you need to do is set the Maps Mode to an instance of the “MercatorMode” object:

<UserControl x:Class="BingMapsSilverlightApplication1.MainPage"
    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;assembly=Microsoft.Maps.MapControl"
    xmlns:mCore="clr-namespace:Microsoft.Maps.MapControl.Core;assembly=Microsoft.Maps.MapControl">
    <Grid x:Name="LayoutRoot">
        <m:Map>
            <m:Map.Mode>
                <!-- Do Not Display Bing Maps Imagery -->
                <mCore:MercatorMode></mCore:MercatorMode>
            </m:Map.Mode>
        </m:Map>
    </Grid>
</UserControl>

 

Display OpenStreetMap Imagery

Next, we will create a simple “OpenStreetMapTileSource” class that inherits from “TileSource” that will be used to specify the location (URI) of the OpenStreetMap Imagery so the Map control can load and display it.

Here’s the simple OpenStreetMapTileSource class:

public class OpenStreetMapTileSource : Microsoft.Maps.MapControl.TileSource
{
    public OpenStreetMapTileSource()
        : base("http://tile.openstreetmap.org/{2}/{0}/{1}.png")
    {
    }

    public override System.Uri GetUri(int x, int y, int zoomLevel)
    {
        return new Uri(string.Format(this.UriFormat, x, y, zoomLevel));
    }
}

 

Now to put the OpenStreetMapTIleSource in place and actually display the OpenStreetMap Imagery. To do this, we will add a new MapTileLayer to the Maps Children collection, and add an instance of our OpenStreetMapTileSource object to the MapTileLayer objects TileSources collection.

Here’s the code to do this:

<UserControl x:Class="BingMapsSilverlightApplication1.MainPage"
    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;assembly=Microsoft.Maps.MapControl"
    xmlns:mCore="clr-namespace:Microsoft.Maps.MapControl.Core;assembly=Microsoft.Maps.MapControl"
    xmlns:local="clr-namespace:BingMapsSilverlightApplication1">
    <Grid x:Name="LayoutRoot">
        <m:Map>
            <m:Map.Mode>
                <!-- Do Not Display Bing Maps Imagery -->
                <mCore:MercatorMode></mCore:MercatorMode>
            </m:Map.Mode>
            <m:Map.Children>
                <m:MapTileLayer>
                    <m:MapTileLayer.TileSources>
                        <!-- Display OpenStreetMap Imagery -->
                        <local:OpenStreetMapTileSource></local:OpenStreetMapTileSource>
                    </m:MapTileLayer.TileSources>
                </m:MapTileLayer>
            </m:Map.Children>
        </m:Map>
    </Grid>
</UserControl>

 

Conclusion

It’s really pretty simple to display your own custom map tile image sets and even completely replace the Bing Maps Imagery with the new control. If your interested in seeing how to display Yahoo Maps imagery within the control, then you’ll want to refer to my previous article on doing this with the CTP version of the Bing Maps Silverlight Control.

C#, Bing Maps, Silverlight , , ,

Getting Started with Bing Maps Silverlight Control v1.0

12. November 2009

BingMapsRTW_BasicMapIt’s been 8 months since the CTP release of the Bing Maps Silverlight Control at MIX’08, and finally this week Microsoft released the Final v1.0 release of the control to the web.  Now, we can all finally start using the Bing Maps Silverlight Control in Production!

If you’ve worked with the CTP, then you’ll want to take a look at Ricky’s “Migrating from Bing Maps Silverlight CTP to Production Version” article. It explains all the stuff you’ll need to modify within your project in order to gracefully switch from the CTP to the v1 Map Control.

Now for those of you who haven’t worked with the CTP…

Where to Start?

First you’ll need to make sure you have the following Tools installed:

Of course you’ll also need to at least be familiar with the basics of Silverlight development. I’m mostly referring to XAML, so if your familiar with WPF that should be enough to get you started.

For those Bing Maps (formerly Virtual Earth) developers new to Silverlight; If you need a little help getting started learning the basics, here are some resources that will help you get started:

Now that you have all the necessary tools installed, you can go ahead and download and install the Bing Maps Silverlight v1 Control.

Download: Bing Maps Silverlight Control SDK Version 1.0

The installer will install the Bing Maps Silverlight Control within the “Program Files” on your computer, along with an SDK Documentation Help (.chm) file.

If you would like to see the Bing Maps Silverligth Control “In Action” and see the source code that powers each example, then you’ll want to check out the Bing Maps Silverlight Control Interactive SDK.

Display a Basic Map

Create a New Silverlight Application Project
  • Run VIsual Studio 2008 and Create a New Project using the Silverlight Application template.
    BingMapsRTW_CreateSilverlightProject
  • In the “Add Silverlight Application” dialog box, select “Host the Silverlight application in a new Web site” option and click “OK”. You must select this option to create an ASP.NET Web Application Project, ASP.NET Website, or ASP.NET MVC Website because the URL Access Restrictions in Silverlight require the page that hosts the Map control be hosted using HTTP in order to load/access the Map TIle Imagery.
    BingMapsRTW_CreateHostWebsite 
Add a Reference to Microsoft.Maps.MapControl.dll
  • Go to the “Solution Explorer” and RIght-Click “ References” in the Silverlight Project (not the ASP.NET Web Application Project), and Select “Add Reference…
    BingMapsRTW_AddReference 
  • Within the “Add Reference“ Dialog, Select the “Browse“ tab and navigate to the folder where the SDK is installed, then select the “Microsoft.Maps.MapControl.dll” and “Microsoft.Maps.MapControl.Common.dll” files.

    Note: Be Default the SDK is installed in this folder on x64 version of Windows: “C:\Program Files (x86)\Bing Maps Silverlight Control\V1\Libraries”. On x86 (or 32-bit) versions of Windows it’s installed within the “Program Files” folder instead of “Program Files (x86)”.

    BingMapsRTW_AddReferenceBrowse 
Display a Bing Maps Map!
  • Add a Namespace declaration to Page.xaml for the Microsoft Maps.MapControl namespace.
    To do this add the following to the <UserControl> tag:
    xmlns:m=”clr-namespace:Microsoft.Maps.MapControl;assembly=Microsoft.Maps.MapControl”
  • Add the Map Control to the Page by adding the following tag within the Grid in the Page:
    <m:Map></m:Map> The resulting Page.xaml will look like this:
    <UserControl x:Class="BingMapsSilverlightApplication1.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
        xmlns:m="clr-namespace:Microsoft.Maps.MapControl;assembly=Microsoft.Maps.MapControl"
        mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
        <Grid x:Name="LayoutRoot">
            <m:Map></m:Map>
        </Grid>
    </UserControl>
    Now, when you run the application (press F5 within Visual Studio) you will see a fully interactive Bing Maps map displayed.
    BingMapsRTW_BasicMap

BingMapsRTW_BasicMapWithDevAccountSignUpWarningSetting Up a Bing Maps Developer Account

When running the above example you may have noticed the “Invalid Credentials. Sign up for a developer account at: http://www.microsoft.com/maps/developers” message being displayed over top of the Map. This is because in order for you to use the Silverlight Map control within an application, Microsoft is requiring you to setup a Developer Account for the domain you will be hosting your application in.

Setup a Bing Maps Developer Account
  • Go to the Bing Maps Account Center at https://www.bingmapsportal.com
  • Click the “Create an Account” link on the left side of the site.
  • Sign in with your Windows Live ID
  • Enter it the required Account Details
Get a Bing Maps Key
BingMapsRTW_CreateBingMapsKey
  • Once you have created a Bing Maps Developer Account, just click the “Create or view keys” link on the left side of the Bing Maps Account Center website.
  • Type in some Application Name. This is your name for the application.
  • Type if the Application URL. This is the domain name that you will be hosting the application at.
  • Click the “Create key” button. Now you have a Bing Maps Key that you can use within your application to get rid of that pesky little warning message displayed over the top of the Map and everything on it.
    Note: For testing purposes I entered in an Application Name of “Test” and Application URL of “http://localhost”. This way I have a Bing Maps Key to use for testing/playing with the Silverlight Map Control that wont track any usage to the application I’ll eventually build.
Use the Bing Maps Key within Your Application

Now that you have a Bing Maps Key for your application, you can set your Map within that application to use this key.

To do so, just set the Map controls “CredentialsProvider” property value within XAML to the Bing Maps Key. Just copy and paste the key from the Bing Maps Account Center into your XAML code.

<UserControl x:Class="BingMapsSilverlightApplication1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:m="clr-namespace:Microsoft.Maps.MapControl;assembly=Microsoft.Maps.MapControl"
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
    <Grid x:Name="LayoutRoot">
        <m:Map CredentialsProvider="[Bing Maps Key Here]"></m:Map>
    </Grid>
</UserControl>

 

Set Map Properties Declaratively Using XAML and Programmatically Using Code

You can change/set the Bing Maps Controls properties Declaratively using XAML, and Programmatically using Code.

Below is an example of setting the Map Mode to Aerial using XAML:

<UserControl x:Class="BingMapsSilverlightApplication1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:m="clr-namespace:Microsoft.Maps.MapControl;assembly=Microsoft.Maps.MapControl"
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
    <Grid x:Name="LayoutRoot">
        <m:Map Mode="Aerial"></m:Map>
    </Grid>
</UserControl>

 

Below is an example of setting the Map Mode to Aerial using C# code:

using System.Windows.Controls;
using Microsoft.Maps.MapControl;

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

            Map1.Mode = new AerialMode();
        }
    }
}

 

First, in order to access the Map Control programmatically you’ll need to assign its “Name”  property within XAML so you have a name to reference it by; like the following:

<UserControl x:Class="BingMapsSilverlightApplication1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:m="clr-namespace:Microsoft.Maps.MapControl;assembly=Microsoft.Maps.MapControl"
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
    <Grid x:Name="LayoutRoot">
        <m:Map Name="Map1"></m:Map>
    </Grid>
</UserControl>

 

Additional Articles

Here are some links to additional articles on using the Bing Maps Silverlight Version 1.0 Control:

Conclusion

It’s pretty exciting that we now have a Bing Maps Silverlight control to use within our applications, and finally there is an option other than the JavaScript Control that has far superior performance when plotting over just a couple hundred Pushpins. Plus the Silverlight controls bring the full power of Silverlight to Bing Maps development; which allows for much richer mapping applications to be built.

Keep an eye out, I’ll be posting more articles/tutorials to help you out in exploring this shiny, new Bing Maps Silverlight Control.

Bing Maps, C#, Silverlight , , ,

Bing Maps Silverlight CTP: Plot/Edit Pushpin data via a ChildWindow

4. August 2009

Silverlight_BingMaps_CTP_EditPushpintsWithChildWindow Recently I posted an example of using the Web.Maps.VE Bing Maps ASP.NET AJAX Server Control with the AjaxControlToolkit ModalPopup Extender over at the Simplovation Blog. Writing that example was rather simple since those two components/libraries are both written on top of ASP.NET AJAX and work extremely well together. This did however get me thinking about how to implement this same type of functionality using the Bing Maps Silveright Control CTP, and now that Silverlight 3 is out and it has a ChildWIndow control, this is actually really simple to implement using Silverlight as well.

This was written for the Bing Maps Silverlight CTP Release.

Download Example Code: Silverlight_BingMaps_CTP_EditPushpinsWithChildWindow.zip (235.44 kb)

To the right you can see a screenshot of this code sample in action. The screenshot in the back is just displaying the plotted “pushpins” as red squares, with tooltip being displayed over the pushpin located in Seattle, WA. The front screenshot is displaying the “Edit” dialog using the ChildWindow control.

Before you hit Run (F5) on this Example Code, you will need to have the Bing Maps Silverlight Map Control SDK CTP Installed.

If you want to see how to use the Silverlight 3 ChildWindow control, I recommend you take a look at Jeff Prosise’s “Silverlight 3’s New Child Windows” post.

Also, if you want to see how to work with the Bing Maps Silverlight Control CTP, then you may want to take a look at the following links:

Bing Maps, Silverlight ,

OpenStreetMap: Get FREE Web Mapping with Road Maps for your Applications

3. August 2009

OpenStreetMapScreenshotOpenStreetMap has been around for awhile and provides free geographic data that can be used by anyone. The data is all community created/contributed and that’s why it’s free to use. Other mapping services such as Bing Maps for Enterprise and Google Maps license their geographic data from some other third party and that’s why they cost thousands of dollars per year to use within commercial applications.

Using OpenStreetMap with JavaScript

The screenshot on the left is showing an example of embedding OpenStreetMap imagery within a web page using OpenLayers. OpenLayers is an open-source, JavaScript-based Map control similar to the Bing Maps for Enterprise JavaScript Control and the Google Maps API; except it’s free to use and offers some decent mapping when combined with OpenStreetMap.

You can find examples of using OpenStreetMap with OpenLayers here: http://wiki.openstreetmap.org/wiki/OpenLayers

Using OpenStreetMap with Silverlight

Unfortunately, there aren’t any open-source Silverlight controls like OpenLayers, but you can easily use OpenStreetMap imagery with the Bing Maps for Enterprise Silverlight Control. Here’s an example of how to do this using the current Bing Maps for Enterprise Silverlight Control Beta release:

Virtual Earth Silverlight: Overlay OpenStreetMap, OpenAerialMap and Yahoo Map Imagery using Custom Tile Layers!

Silverlight, JavaScript, Bing Maps , , ,

Bing Maps Silverlight CTP: Using MouseClick Event To Add "Pushpins"

25. March 2009

In previous tutorials I covered the “Basics of Adding Polygons and Polylines” and “Adding Media (Images, Video, etc.)”, but what about handling user input via Map Events? Well, in this tutorial I’ll cover the basics of working with the Map.MouseClick Event (equivalent of the old “onclick” event in the Virtual Earth JavaScript Control).

This was written for the Bing Maps Silverlight CTP Release.

Adding a MouseClick Event Handler

In order to wire things up to manipulate the Map using the MouseClick event, we must first attach an Event Handler to it. The Event Handler for the MouseClick event needs to be just like any other event handler in .NET; it must accept two parameters: 1) a “sender” object, and 2) an “EventArgs” object.

Before we create our event handler, it’s worth noting that to be more specific, the value that gets passed to the “EventArgs” parameter of the Map.MouseClick event is actually of Type MapMouseEventArgs.

The MapMouseEventArgs object has the following two properties:

  1. Handled – Gets or Sets a value indicating whether the Map event was handled. If you want to prevent the “default” event handling behavior from executing, then all you need to do is set this to True.
  2. ViewportPoint – Gets the viewport point where the mouse event occurred. This is a System.Windows.Point object that represents the X and Y coordinates where the mouse was clicked.

To declare the MouseClick event handler a method that matched the following signature: void(object sender, MapMouseEventArgs e)

Here’s an example Map.MouseClick event handler method:

private void myMap_MouseClick(object sender, MapMouseEventArgs e)
{
}

You can attach the above event handler from within code:

myMap.MouseClick += new EventHandler<MapMouseEventArgs>(myMap_MouseClick);

Or, from within XAML:

<m:Map Name="myMap" MouseClick="myMap_MouseClick"></m:Map>

 

Get the Location (Lat/Long Coordinate) the Mouse was Clicked

One thing that you may have noticed is the MapMouseEventArgs object that is passed to the MouseClick event handler doesn’t contain a “Location” or “LatLong” property of any kind. It’s seems odd at first that there’s no direct way of obtaining the Map Location (Lat/Long) of where the mouse was clicked, but with the help of a little helper method on the Map object itself we can pass in the ViewportPoint (X and Y Coordinates) value contained within the MapMouseEventArgs.ViewportPoint property and get back a Location object with Latitude/Longitude.

To obtain the Location (Lat/Long) where the mouse was clicked, simply invoke the Map.ViewportPointToLocation method by passing in the MapMouseEventArgs.ViewportPoint value.

The following line of code demonstrates how this can be done within the MouseClick Event Handler we defined above:

var location = clickedMap.ViewportPointToLocation(e.ViewportPoint);

Now that we have the  Location of where the mouse was clicked, we can directly access the Latitude and Longitude values.

var lat = location.Latitude;
var lng = location.Longitude;

 

Add a “Pushpin” at the Clicked Location

Now that we have a MouseClick Event Handler in place, and we have access to the Location (Latitude/Longitude) where the mouse was clicked; we can go ahead and add a “Pushpin” to the Map at that Location.

If you have any questions on how to add a Shape or “Pushpin” to the Map, I recommend reading the following two tutorials:

In this example to keep things simple, we’ll add a Square (via the System.Windows.Shapes.Rectangle object) to the Map at the clicked location that is 10x10 in size.

Here’s a full code example of the MouseClick event handler we created above, including code that gets the Location clicked and adds the Rectangle Shape to the Map within a new MapLayer:

private void myMap_MouseClick(object sender, MapMouseEventArgs e)
{
    // Set a variable equal to the Map that raised the event
    Map clickedMap = (Map)sender;
    
    // Convert the X/Y Coordinate that was Clicked to a Lat/Long Location
    var location = clickedMap.ViewportPointToLocation(e.ViewportPoint);

    // Create new MapLayer
    var myLayer = new MapLayer();

    // Create a Rectangle Shape to Show as the "Pushpin"
    var rectangle = new System.Windows.Shapes.Rectangle();
    // Set it's Size to 10x10
    rectangle.Width = 10;
    rectangle.Height = 10;
    // Color the Rectangle Red
    rectangle.Fill = new SolidColorBrush(Colors.Red);

    // Center the Rectangle around the location
    PositionMethod position = PositionMethod.Center;

    // Add Rectangle to MapLayer
    myLayer.AddChild(rectangle, location, position);

    // Add the MapLayer to the Map so the "Pushpin" gets displayed
    clickedMap.AddChild(myLayer);
}

One thing that you may want to do when implementing the above example is create only 1 MapLayer and add all the new “Pushpins” to that single MapLayer. This will help improve performance on the Map if you are adding MANY pushpins. For the simple example above this just wasn’t absolutely necessary.

Auto Expand “Pushpins” using ScaleTransform

The best part of the new Virtual Earth Silverlight Map Control is the fact that we can now leverage the full power of Silverlight within our mapping applications/implementations. One of the cool things that can be done are implementing Animations to spice up the user interface.

Here’s an example that takes the above MouseClick event handler code that adds a Rectangle “Pushpin” to the Map when the user clicks the Map, and adds a ScaleTransform to “Expand” the Rectangle when the user moves the mouse over it.

This is done by setting a ScaleTransform to the Rectangle.RenderTransform during the MouseEnter event, and then removing it during the MouseLeave event. The end result are Rectangle “Pushpins” that Expand when the user Moves the mouse over them.

Here’s the full code for Map.MouseClick, Rectangle.MouseEnter and Rectangle.MouseLeave Event Handlers for this “Expand” Animation example:

// Single MapLayer that will contain all "Pushpins"
private MapLayer myLayer = null;

private void myMap_MouseClick(object sender, MapMouseEventArgs e)
{
    // Set a variable equal to the Map that raised the event
    Map clickedMap = (Map)sender;

    // Convert the X/Y Coordinate that was Clicked to a Lat/Long Location
    var location = clickedMap.ViewportPointToLocation(e.ViewportPoint);

    // Check if MapLayer has already been created
    if (myLayer == null)
    {
        // Create new MapLayer
        myLayer = new MapLayer();

        // Add the MapLayer to the Map so the "Pushpin" gets displayed
        clickedMap.AddChild(myLayer);
    }

    // Create a Rectangle Shape to Show as the "Pushpin"
    var rectangle = new System.Windows.Shapes.Rectangle();
    // Set it's Size to 10x10
    rectangle.Width = 10;
    rectangle.Height = 10;
    // Color the Rectangle Red
    rectangle.Fill = new SolidColorBrush(Colors.Red);

    // Attach MouseEnter and MouseLeave Event Handler to the Rectangle
    // This will be used to "Expand" the Rectangle when the user hovers the mouse over it
    rectangle.MouseEnter += new MouseEventHandler(rectangle_MouseEnter);
    rectangle.MouseLeave += new MouseEventHandler(rectangle_MouseLeave);

    // Center the Rectangle around the location
    PositionMethod position = PositionMethod.Center;

    // Add Rectangle to MapLayer
    myLayer.AddChild(rectangle, location, position);
}

void rectangle_MouseEnter(object sender, MouseEventArgs e)
{
    // Get the Rectangle
    var rectangle = (Rectangle)sender;

    // Create new ScaleTransform
    var scaleTransform = new ScaleTransform();

    // Set the Transform to "Expand" the Rectangle
    // equally horizontally and vertically
    scaleTransform.ScaleX = 2.0;
    scaleTransform.ScaleY = 2.0;

    // Set the Scale Center to the Center of the Rectangle
    // This is so it doesn't move when "Expanded"
    scaleTransform.CenterX = rectangle.Width / 2;
    scaleTransform.CenterY = rectangle.Height / 2;

    // Apply the ScaleTransform to the Rectangle
    rectangle.RenderTransform = scaleTransform;
}

void rectangle_MouseLeave(object sender, MouseEventArgs e)
{
    // Get the Rectangle
    var rectangle = (Rectangle)sender;

    // Remove the ScaleTransform
    rectangle.RenderTransform = null;
}

The above code example also includes a modification from the previous examples in this tutorial; it adds all the new Rectangle “Pushpins” to a Single MapLayer instead of adding a new MapLayer for each Rectangle “Pushpin”.

Conclusion

The Map.MouseClick event is really simple to take advantage of, and it’s actually just as easy to add a “Pushpin” during the “onclick” event with the Virtual Earth Silverlight Map Control as it is with the Virtual Earth JavaScript Control.

There are a few other events that the Map object exposes, and I’ll be covering some of those in additional tutorials. So, keep an eye out for future posts.

Previous Tutorial/Article: Overlay OpenStreetMap, OpenAerialMap and Yahoo Map Imagery using Custom Tile Layers

Bing Maps, Silverlight ,

MIX'09: Virtual Earth Silverlight CTP Session Online for Viewing

21. March 2009

The "Introducing the Microsoft Virtual Earth Silverlight Map Control CTP" session from MIX'09 by Chris Pendlton is now available for your viewing pleasure online.

http://sessions.visitmix.com/MIX09/T34F

Also, here it is below:

Get Microsoft Silverlight

Silverlight, Bing Maps , ,

Bing Maps Silverlight CTP: Overlay OpenStreetMap, OpenAerialMap and Yahoo Map Imagery using Custom Tile Layers!

20. March 2009

UPDATE: I have written a newer version of this article to specifically target the latest Bing Maps Silverlight Control Version 1.0 Release.

You can find the new article here: Display OpenStreetMap Imagery using Bing Maps Silverlight Control v1


In the “Using Tile Layers to Overlay Custom Map Imagery” article I showed you how to overlay your own Custom Map Imagery that you generated using the MapCruncher tool on top of the Map. Now, in this article I’ll show you what you need to know in order to overlay map imagery from other competing mapping services (OpenStreetMap, OpenAerialMap and Yahoo Maps). This allows you to easily build in functionality that allows your users to easily switch (with the click of a button or selection of a dropdown) which mapping service imagery is used to visualize the data in your application.

This was written for the Bing Maps Silverlight CTP Release.

Beware: This article is just a demo of how this is possible. If you do implement this, you need to keep in mind that you’ll need to then adhere to both the Virtual Earth Silverlight Control CTP Terms of Use and the Terms of Use for which ever mapping services data you are displaying.

Before I begin, I’d like to thank the awesome guys that are working on the DeepEarth Project.

Now to the exciting stuff!

Overview of What’s Needed

The steps to create a Tile Layer that displays Map Imagery from the mentions services is very similar to the method mentioned in the “Using Tile Layers to Overlay Custom Map Imagery” arcticle, with the exception that you need to create your own Custom Tile Source object that inherits from TileSource.

Here’s the steps needed to do this:

  1. Create a Custom Tile Source (inheriting from TileSource) object 
    1. Define the “uriFormat” to be used to generate the Uri of the Map Images.
    2. Override the”GetUri” method. This method uses the “uriFormat” to generate the Uri of the Map Images.
  2. Add the Tile Source to the Map
    1. Create a MapTileLayer object instance
    2. Create an instance of you Custom Tile Source object
    3. Add the Custom Tile Source object to the MapTileLayer
    4. Set the MapTileLayer’s Opacity to the desired value
    5. Add the MapTileLayer to the Children collection of the Map

The TileSource objects “GetUri” method takes the following 3 arguments:

  1. x – The horizontal position of the tile.
  2. y – The vertical position of the tile.
  3. zoomLevel – The zoom level of the tile.

You then need to convert (within this method) the x, y, and zoomLevel values into the correct values to be passed using the uriFormat to load the map imagery tiles. This can take a little work in some cases (as with Yahoo Maps) and it an be straight forward in others (as with OpenStreetMap and OpenAerialMap).

Also, when you’re showing Map Imagery that will completely overlay over the top of the Virtual Earth Imagery, it’s a good practice to set the Map’s Mode to an “Empty” mode that will prevent the Virtual Earth imagery from even being downloaded for display. This will increase performance a little (whether you notice it or not), and it will prevent you from using up unnecessary transactions using the Virtual Earth Web Service (this is how the control loads the Virtual Earth imagery behind the scenes.)

Create a TileSource for OpenStreetMap

VEJS_007_OpenStreetMapImageryFirst we need to create custom TileSource object, set the UriFormat to be used to generate the Imagery Uri, and then override the “GetUri” method with code that generates the appropriate Imagery Uri’s using “String.Format”.

The resulting Custom Tile Source object is so simple, it’s probably easier to just show you the code.

namespace VirtualEarthSilverlight01
{
    public class OpenStreetMapTileSource : Microsoft.VirtualEarth.MapControl.TileSource
    {
        public OpenStreetMapTileSource()
            : base("http://tile.openstreetmap.org/{2}/{0}/{1}.png")
        {
        }

        public override Uri GetUri(int x, int y, int zoomLevel)
        {
            return new Uri(String.Format(this.UriFormat, x, y, zoomLevel));
        }
    }
}

 

If you aren’t familiar with the above method of using “String.Format” to replace certain placeholders within a string with specific values, you can reference the MSDN Documentation here.

Now using the described overview above, we can add the new OpenStreetMapTileSource object to a MapTileLayer on the Map and display the OpenStreetMap Imagery within the Silverlight Map Control. Here’s an example of doing this with XAML.

<UserControl x:Class="VirtualEarthSilverlight01.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:m="clr-namespace:Microsoft.VirtualEarth.MapControl;assembly=Microsoft.VirtualEarth.MapControl"
    xmlns:mCore="clr-namespace:Microsoft.VirtualEarth.MapControl.Core;assembly=Microsoft.VirtualEarth.MapControl" 
    xmlns:local="clr-namespace:VirtualEarthSilverlight01"
    Width="1600" Height="768">
    <Grid x:Name="LayoutRoot" Background="White">
        <m:Map Name="MainMap">
            <m:Map.Mode>
                <mCore:MercatorMode></mCore:MercatorMode>
            </m:Map.Mode>
            <m:Map.Children>
                <m:MapTileLayer>
                    <m:MapTileLayer.TileSources>
                        <local:OpenStreetMapTileSource></local:OpenStreetMapTileSource>
                    </m:MapTileLayer.TileSources>
                </m:MapTileLayer>
            </m:Map.Children>
        </m:Map>
    </Grid>
</UserControl>

 

Also, since the OpenStreetMapTileSource object is contained within the projects namespace (“VirtualEarthSilverlight01”) we need to also add a namespace reference to the XAML file. In the example above I’m giving it the prefix of “local”. Once the namespace is included, we can then use our OpenStreetMapTileSource object within the XAML.

Create a TileSource for OpenAerialMap

VEJS_007_OpenAerialMapImageryThe process of creating a Custom Tile Source and adding it to the Map is identical for OpenAerialMap Imagery as the above example for OpenStreetMap; with the exception of the uriFormat that is used to load the imagery. So, I’m not going to re-explain the process all over again. Instead, I’ll just show you the code.

The resulting Custom Tile Source object for showing OpenAerialMap Imagery:

namespace VirtualEarthSilverlight01
{
    public class OpenAerialMapTileSource : Microsoft.VirtualEarth.MapControl.TileSource
    {
        public OpenAerialMapTileSource()
            : base("http://tile.openaerialmap.org/tiles/1.0.0/openaerialmap-900913/{2}/{0}/{1}.jpg")
        {
        }

        public override Uri GetUri(int x, int y, int zoomLevel)
        {
            return new Uri(String.Format(this.UriFormat, x, y, zoomLevel));
        }
    }
}

 

Here’s some example XAML that adds the OpenAerialMapTileSource object to the Map:

<UserControl x:Class="VirtualEarthSilverlight01.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:m="clr-namespace:Microsoft.VirtualEarth.MapControl;assembly=Microsoft.VirtualEarth.MapControl"
    xmlns:mCore="clr-namespace:Microsoft.VirtualEarth.MapControl.Core;assembly=Microsoft.VirtualEarth.MapControl"
    xmlns:local="clr-namespace:VirtualEarthSilverlight01"
    Width="1600" Height="768">
    <Grid x:Name="LayoutRoot" Background="White">
        <m:Map Name="MainMap">

             <m:Map.Mode>
                <mCore:MercatorMode></mCore:MercatorMode>
            </m:Map.Mode> 
            <m:Map.Children>
                <m:MapTileLayer>
                    <m:MapTileLayer.TileSources>
                        <local:OpenAerialMapTileSource></local:OpenAerialMapTileSource>
                    </m:MapTileLayer.TileSources>
                </m:MapTileLayer>
            </m:Map.Children>
        </m:Map>
    </Grid>
</UserControl>

 

Create a TileSource for Yahoo Maps (Street, Aerial and Hybrid)

Again, the process for creating a Custom Tile Source for Yahoo Maps and adding it to the Map is almost identical to the above examples. Except, with Yahoo maps there’s a little math that needs to be done to convert the x, y and zoomLevel arguments that are passed in to the “TileSource.GetUri” method to be the correct values need to load the Yahoo Maps Imagery. I’m not going to cover the process of what’s needed to convert them from the Virtual Earth values to the Yahoo Maps values, but the as you’ll see below the code needed is fairly simple.

Yahoo Maps – Street Imagery

VEJS_007_YahooMapsStreetImageryHere’s the code for the Custom Tile Source for Yahoo Maps Street Imagery:

namespace VirtualEarthSilverlight01
{
    public class YahooStreetTileSource : Microsoft.VirtualEarth.MapControl.TileSource
    {
        public YahooStreetTileSource()
            : base("http://us.maps2.yimg.com/us.png.maps.yimg.com/png?v=3.52&t=m&x={0}&y={1}&z={2}")
        {
        }

        public override Uri GetUri(int x, int y, int zoomLevel)
        {
            // The math used here was copied from the DeepEarth Project (http://deepearth.codeplex.com)
            double posY;
            double zoom = 18 - zoomLevel;
            double num4 = Math.Pow(2.0, zoomLevel) / 2.0;

            if (y < num4)
            {
                posY = (num4 - Convert.ToDouble(y)) - 1.0;
            }
            else
            {
                posY = ((Convert.ToDouble(y) + 1) - num4) * -1.0;
            }

            return new Uri(String.Format(this.UriFormat, x, posY, zoom));
        }
    }
}

 

And, here’s some example XAML that adds the YahooStreetTileSource object to the Map:

<UserControl x:Class="VirtualEarthSilverlight01.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:m="clr-namespace:Microsoft.VirtualEarth.MapControl;assembly=Microsoft.VirtualEarth.MapControl"
    xmlns:mCore="clr-namespace:Microsoft.VirtualEarth.MapControl.Core;assembly=Microsoft.VirtualEarth.MapControl"
    xmlns:local="clr-namespace:VirtualEarthSilverlight01"
    Width="1600" Height="768">
    <Grid x:Name="LayoutRoot" Background="White">
        <m:Map Name="MainMap">

             <m:Map.Mode>
                <mCore:MercatorMode></mCore:MercatorMode>
            </m:Map.Mode> 
            <m:Map.Children>
                <m:MapTileLayer>
                    <m:MapTileLayer.TileSources>
                        <local:YahooStreetTileSource></local:YahooStreetTileSource>
                    </m:MapTileLayer.TileSources>
                </m:MapTileLayer>
            </m:Map.Children>
        </m:Map>
    </Grid>
</UserControl>

 

Yahoo Maps – Aerial Imagery

VEJS_007_YahooMapsAerialImageryHere’s the code for the Custom Tile Source for Yahoo Maps Aerial Imagery:

namespace VirtualEarthSilverlight01
{
    public class YahooAerialTileSource : Microsoft.VirtualEarth.MapControl.TileSource
    {
        public YahooAerialTileSource()
            : base("http://us.maps3.yimg.com/aerial.maps.yimg.com/tile?v=1.7&t=a&x={0}&y={1}&z={2}")
        {
        }

        public override Uri GetUri(int x, int y, int zoomLevel)
        {
            // The math used here was copied from the DeepEarth Project (http://deepearth.codeplex.com)
            double posY;
            double zoom = 18 - zoomLevel;
            double num4 = Math.Pow(2.0, zoomLevel) / 2.0;

            if (y < num4)
            {
                posY = (num4 - Convert.ToDouble(y)) - 1.0;
            }
            else
            {
                posY = ((Convert.ToDouble(y) + 1) - num4) * -1.0;
            }

            return new Uri(String.Format(this.UriFormat, x, posY, zoom));
        }
    }
}

 

And, here’s some example XAML that adds the YahooAerialTileSource object to the Map:

<UserControl x:Class="VirtualEarthSilverlight01.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:m="clr-namespace:Microsoft.VirtualEarth.MapControl;assembly=Microsoft.VirtualEarth.MapControl"
    xmlns:mCore="clr-namespace:Microsoft.VirtualEarth.MapControl.Core;assembly=Microsoft.VirtualEarth.MapControl"
    xmlns:local="clr-namespace:VirtualEarthSilverlight01"
    Width="1600" Height="768">
    <Grid x:Name="LayoutRoot" Background="White">
        <m:Map Name="MainMap">

             <m:Map.Mode>
                <mCore:MercatorMode></mCore:MercatorMode>
            </m:Map.Mode>
            <m:Map.Children>
                <m:MapTileLayer>
                    <m:MapTileLayer.TileSources>
                        <local:YahooAerialTileSource></local:YahooAerialTileSource>
                    </m:MapTileLayer.TileSources>
                </m:MapTileLayer>
            </m:Map.Children>
        </m:Map>
    </Grid>
</UserControl>

 

Yahoo Maps – Hybrid Imagery

VEJS_007_YahooMapsHybridImageryOne thing with the Yahoo Maps Hybrid Imagery is it only shows the roads in the imagery, everything else is transparent. So in order to get the same view as the Virtual Earth Hybrid Map Mode, you need to add the Yahoo Maps Aerial Imagery to the Map, then add the Yahoo Maps Hybrid Imagery so it overlays on top of the the Aerial imagery. You’ll see below that this is really simple to do.

Here’s the code for the Custom Tile Source for Yahoo Maps Hybrid Imagery:

namespace VirtualEarthSilverlight01
{
    public class YahooHybridTileSource : Microsoft.VirtualEarth.MapControl.TileSource
    {
        public YahooHybridTileSource()
            : base("http://us.maps3.yimg.com/aerial.maps.yimg.com/png?v=2.2&t=h&x={0}&y={1}&z={2}”)
        {
        }

        public override Uri GetUri(int x, int y, int zoomLevel)
        {
            // The math used here was copied from the DeepEarth Project (http://deepearth.codeplex.com)
            double posY;
            double zoom = 18 - zoomLevel;
            double num4 = Math.Pow(2.0, zoomLevel) / 2.0;

            if (y < num4)
            {
                posY = (num4 - Convert.ToDouble(y)) - 1.0;
            }
            else
            {
                posY = ((Convert.ToDouble(y) + 1) - num4) * -1.0;
            }

            return new Uri(String.Format(this.UriFormat, x, posY, zoom));
        }
    }
}

 

And, here’s some example XAML that adds the YahooAerialTileSource and YahooHybridTileSource objects to the Map:

<UserControl x:Class="VirtualEarthSilverlight01.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:m="clr-namespace:Microsoft.VirtualEarth.MapControl;assembly=Microsoft.VirtualEarth.MapControl"
    xmlns:mCore="clr-namespace:Microsoft.VirtualEarth.MapControl.Core;assembly=Microsoft.VirtualEarth.MapControl"
    xmlns:local="clr-namespace:VirtualEarthSilverlight01"
    Width="1600" Height="768">
    <Grid x:Name="LayoutRoot" Background="White">
        <m:Map Name="MainMap">
            <m:Map.Mode>
                <mCore:MercatorMode></mCore:MercatorMode>
            </m:Map.Mode>
            <m:Map.Children>
                <m:MapTileLayer>
                    <m:MapTileLayer.TileSources>
                        <local:YahooAerialTileSource></local:YahooAerialTileSource>
                        <local:YahooHybridTileSource></local:YahooHybridTileSource>
                    </m:MapTileLayer.TileSources>
                </m:MapTileLayer>
            </m:Map.Children>
        </m:Map>
    </Grid>
</UserControl>

 

Conclusion

As you can see, the ability to overlay custom map imagery of any kind (like OpenStreetMap or Yahoo Maps Imagery) really offers some great flexibility in the control. Plus, it’s easy to do!

Previous Tutorial/Article: Using Tile Layers to Overlay Custom Map Imagery 

Next Tutorial/Article: Using MouseClick Event To Add "Pushpins"

Bing Maps, Silverlight , ,

Bing Maps Silverlight CTP: Using Tile Layers to Overlay Custom Map Imagery

20. March 2009

One of the features that the Virtual Earth JavaScript Control has is the ability to add custom Tile Layers to overlay your own custom imagery over the map. The Virtual Earth Silverlight control also supports this feature.

This was written for the Bing Maps Silverlight CTP Release.

Before I begin to explain how to add custom Tile Layers to the Map it’s important to note that you can still use the MapCruncher tool to generate Map Imagery Tiles to be used with the custom Tile Layers. The specifics of using the MapCruncher tool to generate Map Imagery Tiles isn’t within the scope of this article. You can find a tutorial on how to use MapCruncher here: http://research.microsoft.com/en-us/um/redmond/projects/mapcruncher/tutorial/version3.0docs/index.htm

Add Custom Tile Layer using Code

VEJS_006_CustomTileLayerOnce you have some custom Map Imagery Tiles generated from using MapCruncher, you can then add them using an instance of the LocationRectTileSource object and adding it to a MapTileLayer on the Map.

To do this we will following the below steps:

  1. Create a MapTileLayer object
  2. Create a LocationRect object that defines the bounding rectangle for our map tile overlay
  3. Create a LocationRectTileSource
    1. Point it to the Uri of our custom Map Imagery Tiles
    2. Set the Minimum and Maximum Zoom Levels (ZoomRange) that the imagery is to be visible within
    3. Set the Bouding Rectangle to the LocationRect object we previously created
  4. Add the LocationRectTileSource to the MapTileLayer’s TileSources collection property
  5. Set the MapTileLayer’s Opacity to the desired value
  6. Add the MapTileLayer to the Children collection of the Map

Here’s some sample code that will add a custom Tile Layer using the imagery that the JavaScript Map Controls SDK uses as an example for this same thing:

// Create a Tile Layer that will display our custom Map Imagery Tiles
var customTileLayer = new MapTileLayer();

// Define the Bounding Rectangle
LocationRect boundingRect = new LocationRect(
    new Location(49, -123), 
    new Location(47, -121)
);

// Create a LocationRectTileSource
LocationRectTileSource customTileSource = new LocationRectTileSource();

// Set the Uri for the custom Map Imagery Tiles
customTileSource.UriFormat = "http://dev.live.com/virtualearth/sdk/layers/lidar/{0}.png";

// Set the Min and Max Zoom Levels that the imagery is to be visible within
customTileSource.ZoomRange = new Range<double>(10, 18);

// The bounding rectangle area that the tile overaly is valid in.
customTileSource.BoundingRectangle = boundingRect;

// Add the Tile Source to the Tile Layer
customTileLayer.TileSources.Add(customTileSource);

// Set the Tile Layer Opacity to a desired value
customTileLayer.Opacity = 0.7;

Map1.Children.Add(customTileLayer);

 

Hide Virtual Earth Imagery From Being Displayed

Sometimes you may want to hide the Virtual Earth Imagery from being displayed altogether. To do this all you need to do is set the Map’s Mode property to a new instance of the MercatorMode object. Doing this allows you to show only your custom map imagery.

Using XAML:

<UserControl x:Class="VirtualEarthSilverlightApplication1.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:m="clr-namespace:Microsoft.VirtualEarth.MapControl;assembly=Microsoft.VirtualEarth.MapControl"
    xmlns:mc="clr-namespace:Microsoft.VirtualEarth.MapControl.Core;assembly=Microsoft.VirtualEarth.MapControl"
    Width="800" Height="600">
    <Grid x:Name="LayoutRoot" Background="White">
        <m:Map Name="Map1">
            <m:Map.Mode>
                <mc:MercatorMode></mc:MercatorMode>
            </m:Map.Mode>
        </m:Map>
    </Grid>
</UserControl>

 

Using Code:

Map1.Mode = new Microsoft.VirtualEarth.MapControl.Core.MercatorMode();

 

A little more intuitively

Alternatively, you can also create your own EmptyMapMode object that inherits from the MercatorMode object. This way your code will be a little more intuitive to read.

Here’s example of doing this:

<UserControl x:Class="VirtualEarthSilverlightApplication1.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:m="clr-namespace:Microsoft.VirtualEarth.MapControl;assembly=Microsoft.VirtualEarth.MapControl"
    xmlns:local="clr-namespace:VirtualEarthSilverlightApplication1"
    Width="800" Height="600">
    <Grid x:Name="LayoutRoot" Background="White">
        <m:Map Name="Map1">
            <m:Map.Mode>
                <local:EmptyMapMode></local:EmptyMapMode>
            </m:Map.Mode>
        </m:Map>
    </Grid>
</UserControl>

 

As you notice above, since our custom EmptyMapMode object is contained within the “VirtualEarthSilverlightApplication1” namespace, we need to add that namespace to the XAML file in order to use it.

And, here’s the EmptyMapMode object shown in use above:

public class EmptyMapMode :Microsoft.VirtualEarth.MapControl.Core.MercatorMode
{
}

 

Conclusion

If you are familiar with the JavaScript Map Control you can see that it’s pretty much just as simple to overly your own custom map imagery tiles on the map. One thing to note is that the LocationRectTileSource inherits from the TileSource object; so presumably you could inherit from the TileSource object yourself to create write code that pulls in map imagery from any source using your own custom TileSource object.

Next Tutorial/Article: Overlay OpenStreetMap, OpenAerialMap and Yahoo Maps Imagery using Custom Tile Layers!

Previous Tutorial/Article: Adding Media (Images, Video, etc.) to the Map

Bing Maps, Silverlight ,