====== Map Suite Silverlight Edition Quick Start Guide ======
using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Resources;
using ThinkGeo.MapSuite.SilverlightEdition;
namespace HelloWorld
{
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
Loaded += new RoutedEventHandler(Page_Loaded);
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
Map1.MapUnit = GeographyUnit.DecimalDegree;
ShapeFileFeatureLayer statesLayer = new ShapeFileFeatureLayer("STATES.SHP");
// Add a handler to load shape files from resource.
// If you remove this handler, the map control will find Shape files from isolatedStorage,
// so in that case, please make sure your Shape file is in the isolatedStorage first.
((ShapeFileFeatureSource)statesLayer.FeatureSource).StreamLoading += new EventHandler(StatesLoadAShapeFile_StreamLoading);
// Set the statesLayer's style
statesLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(255, 243, 239, 228), GeoColor.FromArgb(255, 218, 193, 163), 1);
// This setting will apply from ZoonLevel01 to ZoomLevel20.
// That means we display the map in the same style as ZoomLevel01 at all times, no matter how far we zoom in or out.
statesLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
// We need to add the world layer to its overlay.
LayerOverlay layerOverlay = new LayerOverlay();
layerOverlay.Layers.Add(statesLayer);
// We need to add the overlay to the map.
Map1.Overlays.Add(layerOverlay);
// Set a proper center and zoom level Id for the map; that's the place you want it to display.
// Please see the overload of this method.
Map1.ZoomTo(new PointShape(-100, 35), 4);
}
// Load Shape files from resource.
private void StatesLoadAShapeFile_StreamLoading(object sender, StreamLoadingEventArgs e)
{
switch (System.IO.Path.GetExtension(e.AlternateStreamName).ToLower())
{
case ".shp":
StreamResourceInfo sr = Application.GetResourceStream(new Uri(@"App_Data/STATES.SHP", UriKind.RelativeOrAbsolute));
e.AlternateStream = sr.Stream;
break;
case ".dbf":
e.AlternateStream = Application.GetResourceStream(new Uri("App_Data/STATES.DBF", UriKind.RelativeOrAbsolute)).Stream;
break;
case ".shx":
e.AlternateStream = Application.GetResourceStream(new Uri("App_Data/STATES.SHX", UriKind.RelativeOrAbsolute)).Stream;
break;
case ".idx":
e.AlternateStream = Application.GetResourceStream(new Uri("App_Data/STATES.idx", UriKind.RelativeOrAbsolute)).Stream;
break;
case ".ids":
e.AlternateStream = Application.GetResourceStream(new Uri("App_Data/STATES.ids", UriKind.RelativeOrAbsolute)).Stream;
break;
default:
break;
}
}
}
}
If you compile and run what you have now, your map should look like the one below. (See Figure 9)
{{silverlightedition:QSG_Silverlight_Img09.png}}
\\
//Figure 9. A simple map of the US.//
==== Navigate the Map ====
With the code above, not only can you display a map, but you can also navigate it. You can pan by dragging the map; track zoom in by drawing a rectangle with your left mouse button mouse while holding the shift key; navigate by using the controls at the top left corner of the map, or zoom in and out by using the mouse wheel. Very powerful for just couple lines of code, isn't it?
===== How to Use the TextStyle =====
==== TextStyle ====
The TextStyle is used to label items on map. Because every Shape file has a related .dbf file that includes descriptions for each record, the most common way to use the TextStyle is for labeling. For example, the Shape file containing the names of the states of the US has a corresponding .dbf file that contains the field "STATE_NAME". We can use this field to label the states on our map. (See Figure 10)
{{silverlightedition:QSG_Silverlight_Img10.png}}
\\
//Figure 10. The STATE_NAME column in the DBF file.//
Map Suite has many TextStyles built in that will help us quickly design attractive labels for the states on our map. We can just pick the TextStyle we like and use it.
private void Page_Loaded(object sender, RoutedEventArgs e)
{
Map1.MapUnit = GeographyUnit.DecimalDegree;
ShapeFileFeatureLayer statesLayer = new ShapeFileFeatureLayer("STATES.SHP");
((ShapeFileFeatureSource)statesLayer.FeatureSource).StreamLoading += new EventHandler(StatesLoadAShapeFile_StreamLoading);
statesLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(255, 243, 239, 228), GeoColor.FromArgb(255, 218, 193, 163), 1);
// We'll use a preset TextStyle. Here we passed in the "STATE_NAME", which is the name of the field we want to display on map.
statesLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = TextStyles.Canal1("STATE_NAME");
statesLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
LayerOverlay layerOverlay = new LayerOverlay();
layerOverlay.Layers.Add(statesLayer);
Map1.Overlays.Add(layerOverlay);
// Set the center and zoom level Id to locate the map's position.
Map1.ZoomTo(new PointShape(-100, 35), 4);
}
The result is as follows (Figure 11):
{{silverlightedition:QSG_Silverlight_Img11.png}}
\\
//Figure 11. Map of the US with states labeled.//
Now that we know how to render text and render symbols, let's define two different ZoomLevels for one single layer.
private void Page_Loaded(object sender, RoutedEventArgs e)
{
Map1.MapUnit = GeographyUnit.DecimalDegree;
// Set the background color to make the map beautiful.
Map1.Background = new SolidColorBrush(Color.FromArgb(255, 156, 187, 216));
ShapeFileFeatureLayer statesLayer = new ShapeFileFeatureLayer("STATES.SHP");
((ShapeFileFeatureSource)statesLayer.FeatureSource).StreamLoading += new EventHandler(StatesLoadAShapeFile_StreamLoading);
statesLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(255, 243, 239, 228), GeoColor.FromArgb(255, 218, 193, 163), 1);
statesLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = TextStyles.Canal1("STATE_NAME");
statesLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level05;
statesLayer.ZoomLevelSet.ZoomLevel06.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromHtml("#EFEFEF"), GeoColor.FromHtml("#CCCCCC"), 1);
statesLayer.ZoomLevelSet.ZoomLevel06.DefaultTextStyle = TextStyles.Capital3("STATE_NAME");
statesLayer.ZoomLevelSet.ZoomLevel06.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
LayerOverlay layerOverlay = new LayerOverlay();
layerOverlay.Layers.Add(statesLayer);
Map1.Overlays.Add(layerOverlay);
Map1.ZoomTo(new PointShape(-100, 35), 4);
}
Can you imagine what the map will look like now? Figures 12 and 13 below demonstrate the result. At first it looks the same as it did in Figure 11. Now zoom in, and watch the map change to resemble Figure 13 as you do.
{{silverlightedition:QSG_Silverlight_Img12.png}}
\\
//Figure 12. Map of US states with two ZoomLevels, before zooming in.//
{{silverlightedition:QSG_Silverlight_Img13.png}}
\\
//Figure 13. Map of US states two ZoomLevels, after zooming in.//
===== How to Render a Map at the Server Side =====
If there are too many shapes drawn at the client side, the performance of your Silverlight application will slow down. To get around this, you can choose to render an overlay at the server side. The following steps will show you how to do that.
==== ServerLayerOverlay ====
This overlay helps you create a simple WMS server, which is used by the map control to get map tile images.
First, copy the country shape file data into the web project:
{{silverlightedition:QSG_Silverlight_Img19.png}}
You may be asking how the ServerOverlay gets rendered on the client side. In the "SilverlightEdition.dll", there is a ''ServerOverlay'' object which, on the client side, is just a "shell" that will accept the actual overlay that is created on the server side by the "SilverlightMapConnector.dll". We use a connector ID to keep track of these overlays as they pass from the server to the client side.
**Code in "Default.aspx.cs" in the Silverlight project:**
using System;
using System.Web.UI;
using ThinkGeo.MapSuite.Core;
using ThinkGeo.MapSuite.SilverlightEdition;
namespace HelloWorld.Web
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
ShapeFileFeatureLayer worldLayer = new ShapeFileFeatureLayer(MapPath("~/app_data/cntry02.shp"));
worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(255, 243, 239, 228), GeoColor.FromArgb(255, 218, 193, 163), 1);
worldLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
ServerLayerOverlay layerOverlay = new ServerLayerOverlay("NativeServer");
layerOverlay.Layers.Add(worldLayer);
SilverlightMapConnector1.ServerLayerOverlays.Add(layerOverlay);
}
}
}
}
**Code in "Page.xaml.cs" in the Silverlight project:**
private void Page_Loaded(object sender, RoutedEventArgs e)
{
Map1.MapUnit = GeographyUnit.DecimalDegree;
Map1.Background = new SolidColorBrush(Color.FromArgb(255, 156, 187, 216));
ServerLayerOverlay serverOverlay = new ServerLayerOverlay("NativeServer", "SilverlightMapConnector1");
Map1.Overlays.Add(serverOverlay);
ShapeFileFeatureLayer statesLayer = new ShapeFileFeatureLayer("STATES.SHP");
((ShapeFileFeatureSource)statesLayer.FeatureSource).StreamLoading += new EventHandler(StatesLoadAShapeFile_StreamLoading);
statesLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(255, 243, 239, 228), GeoColor.FromArgb(255, 218, 193, 163), 1);
statesLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = TextStyles.Canal1("STATE_NAME");
statesLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level05;
statesLayer.ZoomLevelSet.ZoomLevel06.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromHtml("#EFEFEF"), GeoColor.FromHtml("#CCCCCC"), 1);
statesLayer.ZoomLevelSet.ZoomLevel06.DefaultTextStyle = TextStyles.Capital3("STATE_NAME");
statesLayer.ZoomLevelSet.ZoomLevel06.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
LayerOverlay layerOverlay = new LayerOverlay();
layerOverlay.Layers.Add(statesLayer);
Map1.Overlays.Add(layerOverlay);
Map1.ZoomTo(new PointShape(-100, 35), 4);
}
Don't forget to set the "Default.aspx" file as the Start Page. Click "Run" to see what the map looks like.
{{silverlightedition:QSG_Silverlight_Img20.png}}
{{silverlightedition:QSG_Silverlight_Img21.png}}
===== Summary =====
You now know the basics of using Map Suite Silverlight Edition and are able to start adding this functionality into your own applications. Let's recap what we have learned about the object relationships and how the pieces of Map Suite work together:
- It is of the utmost importance that the units of measurement (feet, meters, decimal degrees, etc.) be set properly for the map, based on the requirements of your data.
- Shape files provide the data used by Map Suite to render a map. You can choose to load them from a resource or memory.
- A Map is the basic class that contains all of the other objects that are used to define how the map will be rendered.
- A Map has one-to-many Overlays. An Overlay contains one-to-many Layers. A Layer contains the data (from Shape files or other data source) for drawing.
- A Layer can have one-to-many ZoomLevels. ZoomLevels help to define ranges of when a layer should be shown or hidden.