User Tools

Site Tools


map_suite_desktop_for_winforms_quick_start_guide

Map Suite Quick Start Guide For WinForms

The Winforms Quickstart Guide will guide you through the process of creating a sample application and will help you become familiar with Map Suite. This Quickstart Guide supports Map Suite 10.0.0.0 and higher and will show you how to create a Winforms application.

If you want to build a WPF application, please see the WPF Quickstart Guide instead.

Welcome to Map Suite™ from ThinkGeo, a full featured mapping control that makes it easy for any Microsoft .NET developer to add mapping functionality to a Microsoft .NET application quickly and efficiently. Using the intuitive object model, even developers inexperienced in Geographic Information Systems (GIS) can have fully functional maps working in minutes.

The purpose of this guide is to help you quickly get started building your own spatially aware applications. Like any new software, there is some learning to be done. How do we start to learn how to take advantage of the power of Map Suite? The best way is to make a sample application with it.

Download the Sample

Setting up the Environment

Let's start by creating a new Windows Forms Application in Microsoft Visual Studio (2015 or newer) named QuickstartSample(see Figure 1). We can create the project with .NET Framework 4.5 or higher.


Figure 1. Creating a new project in Microsoft Visual Studio.

After you created a QuickstartSample project, we will see a project in the solution, please see Figure 2.


Figure 2. Create WinForms Project.

Adding a NuGet Package to our Project

You need to add the Map Suite Desktop for WinForms package to the “QuickstartSample” project from NuGet. Right-click the Reference in Solution Explorer and select “Manage NuGet Packages” (See Figure 3).

Figure 3. Refer to Manage NuGet Packages.

You can see the NuGet Package management start page in our Microsoft Visual Studio main window. Ensure that “Browse” is selected and then type “MapSuiteDesktopForWinForms” in the search box then press enter. You should see a package list (See Figure 4) in the main window. In that package list, please select “MapSuiteDesktopForWinForms-Standard” package and click the “Install” button in the right panel.

Figure 4. Refer to MapSuiteDesktopForWinForms-Standard.

Click “OK” if the message box like Figure 5 pops up.

Figure 5. Review package references.

The “NetTopologySuite” is the third part assembly, so the license acceptance is required. You can click “I Accept” to agree the license.(See Figure 6)

Figure 6. NuGet installation success.

Once the package is installed, you can see the message “Successfully installed 'MapSuiteDesktopForWinForms-Standard' to QuickstartSample” in your Microsoft Visual Studio Output box. Some Desktop assemblies have been added into the project references. (See Figure 7).


Figure 7. NuGet installation result.

Adding the Map Control to Your Form

Open “…/QuickstartSample/packages/MapSuiteDesktopForWinForms-Standard.10.0.0/designtime” package folder and drag “ThinkGeo.MapSuite.WinForms.dll” assembly to the Toolbox of Visual Studio.

Draw the Map control on the form by clicking on the WinformsMap Control object in the Toolbox and then dragging and dropping (using the left mouse button) to the form. You can resize the map if you desire. You can leave the name of the Map control as winformsMap1. Our map will display in this object.

Map Suite Desktop "QuickstartSample"

In creating your “QuickstartSample“ application, your first step is to set some references at the very top of your code as you will use many classes within that. Open the “Form1.cs” in the project and click the form in the opened design box to move to the “View Code” of the form. Add the references like this:

using ThinkGeo.MapSuite;
using ThinkGeo.MapSuite.WinForms; 
using ThinkGeo.MapSuite.Layers;
using ThinkGeo.MapSuite.Styles;
using ThinkGeo.MapSuite.Shapes;
using ThinkGeo.MapSuite.Drawing;

Now let's look at a code sample to bring this concept to fruition. We'll look at Shapefiles relating to the entire world. In our example, we have one such Shapefile:

  • The borders of every country in the world (“Countries02.shp”)

(NOTE: The data used in this sample can be found in the attached sample above in the “\Data” folder)

Our next step is to define and add our layers. All of the following code can be placed in the Form1_Load event of the form. Here is the code to use for our example.

private void Form1_Load(object sender, EventArgs e)
{
    // Set the Map Unit. The reason for setting it to DecimalDegrees is that is what the shapefile’s unit of measure is inherently in.
    winformsMap1.MapUnit = GeographyUnit.DecimalDegree;
 
    // We create a new Layer and pass the path to a Shapefile into its constructor. 
    ShapeFileFeatureLayer worldLayer = new ShapeFileFeatureLayer(@"../../Data/Countries02.shp");
    AreaStyle areaStyle = new AreaStyle();
    areaStyle.FillSolidBrush = new GeoSolidBrush(GeoColor.FromArgb(255, 233, 232, 214));
    areaStyle.OutlinePen = new GeoPen(GeoColor.FromArgb(255, 118, 138, 69), 1);
    areaStyle.OutlinePen.DashStyle = LineDashStyle.Solid;
 
    // Set the worldLayer with a preset Style.  
    worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = areaStyle;
 
    // This setting will apply from ZoonLevel01 to ZoomLevel20, that means we can see the world the same style with ZoomLevel01 all the time no matter how far we zoom out/in. 
    worldLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
 
    // Create a new Layer Overlay to hold the layer we just created
    LayerOverlay layerOverlay = new LayerOverlay();
 
    // Add the shapefile layer to the layer overlay
    layerOverlay.Layers.Add(worldLayer);
 
    // We need to add the layer overlay to Map.
    winformsMap1.Overlays.Add(layerOverlay);
 
    // Set a proper extent for the Map.  
    winformsMap1.CurrentExtent = new RectangleShape(-134, 70, -56, 7);
 
    // We now need to call the Refresh() method of the Map control so that the Map can redraw based on the data that has been provided.
    winformsMap1.Refresh();
}

Now it is time to press F5 to start the application. If you have not set up a developer license, the Map Suite Product Center will pop up. You need to generate your developer license. For more details, please refer to http://wiki.thinkgeo.com/wiki/map_suite_developer_license_guide.

Once the developer license is ready, run the application. Your map should look like the one below: (see Figure 12).


Figure 12. A sample map of Europe.

So what has occurred here? We have created a layer and added it to the map and the map has rendered according to its default style parameters. Also, we have used ZoomLevel to display the map the way that we want.

NOTE: It is important that the “MapUnit” property of a Map object be set using the “GeographyUnit” enumeration. This is because ShapeFiles only store binary vector coordinates, which can be in DecimalDegree, feet, meters, etc. Our map has no idea about what the unit of measurement is until we set it. This information is normally found somewhere in the documentation or within the supplemental data file as discussed in the section on ShapeFiles.

With the above code, you can both display a map and navigate it. You can pan by dragging the map, zoom in by double-clicking, track zoom in by drawing a rectangle with your left mouse button mouse while holding the shift key, or zoom in and out by using the mouse wheel. Very powerful for just couple lines of code, isn't it?

That was an easy start! Now, let's add another Shapefile to the sample so that we will have a total of two layers:

  1. The borders of every country in the world (“Countries02.shp”)
  2. The capitals of the world countries (“WorldCapitals.shp”)
private void Form1_Load(object sender, EventArgs e)
{
    winformsMap1.MapUnit = GeographyUnit.DecimalDegree;
 
    ShapeFileFeatureLayer worldLayer = new ShapeFileFeatureLayer(@"../../Data/Countries02.shp");
    AreaStyle areaStyle = new AreaStyle();
    areaStyle.FillSolidBrush = new GeoSolidBrush(GeoColor.FromArgb(255, 233, 232, 214));
    areaStyle.OutlinePen = new GeoPen(GeoColor.FromArgb(255, 118, 138, 69), 1);
    areaStyle.OutlinePen.DashStyle = LineDashStyle.Solid;
    worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = areaStyle;
    worldLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
 
    ShapeFileFeatureLayer capitalLayer = new ShapeFileFeatureLayer(@"../../Data/WorldCapitals.shp");
    // Similarly, we use the presetPointStyle for cities. 
    PointStyle pointStyle = new PointStyle();
    pointStyle.SymbolType = PointSymbolType.Square;
    pointStyle.SymbolSolidBrush = new GeoSolidBrush(GeoColor.StandardColors.White);
    pointStyle.SymbolPen = new GeoPen(GeoColor.StandardColors.Black, 1);
    pointStyle.SymbolSize = 6;
 
    capitalLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = pointStyle;
    // This setting also applies from ZoonLevel01 to ZoomLevel20, that means we can see city symbols the same style with ZoomLevel01 all the time. 
    capitalLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
 
    LayerOverlay layerOverlay = new LayerOverlay();
    layerOverlay.Layers.Add(worldLayer);
    // We need to add both of the new layers to the Layer OverLay. 
    layerOverlay.Layers.Add(capitalLayer);
 
    winformsMap1.Overlays.Add(layerOverlay);
    winformsMap1.CurrentExtent = new RectangleShape(-134, 70, -56, 7);
 
    winformsMap1.Refresh();
}

And the result is as follows (Figure 13):


Figure 13. Map of Europe with 2 layers.

How to Use GeoTextStyle

TextStyle

A TextStyle is used to label items on map. As every ShapeFile has a relative .dbf file that includes descriptions for every record, the most common way to use TextStyles is for labeling. For example, WorldCapital Shapefile's corresponding .dbf file contains the field “CITY_NAME”. We can use this field to label the cities on our map.

Map Suite has many TextStyles built in to help us quickly design attractive labels for the cities on our map. We can just pick the TextStyle we like and use it.

private void Form1_Load(object sender, EventArgs e)
{
    winformsMap1.MapUnit = GeographyUnit.DecimalDegree;
 
    ShapeFileFeatureLayer worldLayer = new ShapeFileFeatureLayer(@"../../Data/Countries02.shp");
    AreaStyle areaStyle = new AreaStyle();
    areaStyle.FillSolidBrush = new GeoSolidBrush(GeoColor.FromArgb(255, 233, 232, 214));
    areaStyle.OutlinePen = new GeoPen(GeoColor.FromArgb(255, 118, 138, 69), 1);
    areaStyle.OutlinePen.DashStyle = LineDashStyle.Solid;
    worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = areaStyle;
    worldLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
 
    ShapeFileFeatureLayer capitalLayer = new ShapeFileFeatureLayer(@"../../Data/WorldCapitals.shp");
    // Similarly, we use the presetPointStyle for cities. 
    PointStyle pointStyle = new PointStyle();
    pointStyle.SymbolType = PointSymbolType.Square;
    pointStyle.SymbolSolidBrush = new GeoSolidBrush(GeoColor.StandardColors.White);
    pointStyle.SymbolPen = new GeoPen(GeoColor.StandardColors.Black, 1);
    pointStyle.SymbolSize = 6;
 
    PointStyle stackStyle = new PointStyle();
    stackStyle.SymbolType = PointSymbolType.Square;
    stackStyle.SymbolSolidBrush = new GeoSolidBrush(GeoColor.StandardColors.Maroon);
    stackStyle.SymbolPen = new GeoPen(GeoColor.StandardColors.Transparent, 0);
    stackStyle.SymbolSize = 2;
 
    pointStyle.CustomPointStyles.Add(stackStyle);
    capitalLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = pointStyle;
    // This setting also applies from ZoonLevel01 to ZoomLevel20, that means we can see city symbols the same style with ZoomLevel01 all the time. 
    capitalLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
 
    // We create a new Layer for labeling the capitals.
    ShapeFileFeatureLayer capitalLabelLayer = new ShapeFileFeatureLayer(@"../../Data/WorldCapitals.shp");
    // We use the preset TextStyle. Here we passed in the “CITY_NAME”, which is the name of the field we want to label on map.
    GeoFont font = new GeoFont("Arial", 9, DrawingFontStyles.Bold);
    GeoSolidBrush txtBrush = new GeoSolidBrush(GeoColor.StandardColors.Maroon);
    TextStyle textStyle = new TextStyle("CITY_NAME", font, txtBrush);
    textStyle.XOffsetInPixel = 0;
    textStyle.YOffsetInPixel = -6;
    capitalLabelLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = textStyle;
    capitalLabelLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
    // As the map is drawn by tiles, it needs to draw on the margin to make sure the text is complete after we joining the tiles together.
    // Change the number to another one (for example 0) and you can see the difference expecially when panning.
 
    LayerOverlay layerOverlay = new LayerOverlay();
    layerOverlay.Layers.Add(worldLayer);
    layerOverlay.Layers.Add(capitalLayer);
    layerOverlay.Layers.Add(capitalLabelLayer);
 
    winformsMap1.Overlays.Add(layerOverlay);
    winformsMap1.CurrentExtent = new RectangleShape(-134, 70, -56, 7);
 
    winformsMap1.Refresh();
}

The result is as follows (Figure 14):


Figure 14. Map of Europe with a TextStyle.

Now that we know how to render text and render symbols, let's define two different ZoomLevels in one single layer and create our own custom Style and TextStyle.

private void Form1_Load(object sender, EventArgs e)
{
    winformsMap1.MapUnit = GeographyUnit.DecimalDegree;
 
    ShapeFileFeatureLayer worldLayer = new ShapeFileFeatureLayer(@"../../Data/Countries02.shp");
    AreaStyle areaStyle = new AreaStyle();
    areaStyle.FillSolidBrush = new GeoSolidBrush(GeoColor.FromArgb(255, 233, 232, 214));
    areaStyle.OutlinePen = new GeoPen(GeoColor.FromArgb(255, 118, 138, 69), 1);
    areaStyle.OutlinePen.DashStyle = LineDashStyle.Solid;
    worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = areaStyle;
    worldLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
 
    ShapeFileFeatureLayer capitalLayer = new ShapeFileFeatureLayer(@"../../Data/WorldCapitals.shp");
    PointStyle pointStyle = new PointStyle();
    pointStyle.SymbolType = PointSymbolType.Square;
    pointStyle.SymbolSolidBrush = new GeoSolidBrush(GeoColor.StandardColors.White);
    pointStyle.SymbolPen = new GeoPen(GeoColor.StandardColors.Black, 1);
    pointStyle.SymbolSize = 6;
 
    PointStyle stackStyle = new PointStyle();
    stackStyle.SymbolType = PointSymbolType.Square;
    stackStyle.SymbolSolidBrush = new GeoSolidBrush(GeoColor.StandardColors.Maroon);
    stackStyle.SymbolPen = new GeoPen(GeoColor.StandardColors.Transparent, 0);
    stackStyle.SymbolSize = 2;
 
    pointStyle.CustomPointStyles.Add(stackStyle);
    // We can customize our own Style. Here we passed in a color and a size.
    capitalLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.CreateSimpleCircleStyle(GeoColor.StandardColors.White, 7, GeoColor.StandardColors.Brown);
    // The Style we set here is available from ZoomLevel01 to ZoomLevel05. That means if we zoom in a bit more, the appearance we set here will not be visible anymore.
    capitalLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level05;
 
    capitalLayer.ZoomLevelSet.ZoomLevel06.DefaultPointStyle = pointStyle;
    // The Style we set here is available from ZoomLevel06 to ZoomLevel20. That means if we zoom out a bit more, the appearance we set here will not be visible any more.
    capitalLayer.ZoomLevelSet.ZoomLevel06.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
 
    ShapeFileFeatureLayer capitalLabelLayer = new ShapeFileFeatureLayer(@"../../Data/WorldCapitals.shp");
    // We can customize our own TextStyle. Here we passed in the font, the size, the style and the color.
    GeoFont font = new GeoFont("Arial", 9, DrawingFontStyles.Bold);
    GeoSolidBrush txtBrush = new GeoSolidBrush(GeoColor.StandardColors.Maroon);
    TextStyle textStyle = new TextStyle("CITY_NAME", font, txtBrush);
    textStyle.XOffsetInPixel = 0;
    textStyle.YOffsetInPixel = -6;
    capitalLabelLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = TextStyles.CreateSimpleTextStyle("CITY_NAME", "Arial", 8, DrawingFontStyles.Italic, GeoColor.StandardColors.Black, 3, 3);
    // The TextStyle we set here is available from ZoomLevel01 to ZoomLevel05. 
    capitalLabelLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level05;
 
    capitalLabelLayer.ZoomLevelSet.ZoomLevel06.DefaultTextStyle = textStyle;
    // The TextStyle we set here is available from ZoomLevel06 to ZoomLevel20. 
    capitalLabelLayer.ZoomLevelSet.ZoomLevel06.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
 
    LayerOverlay layerOverlay = new LayerOverlay();
    layerOverlay.Layers.Add(worldLayer);
    layerOverlay.Layers.Add(capitalLayer);
    layerOverlay.Layers.Add(capitalLabelLayer);
 
    winformsMap1.Overlays.Add(layerOverlay);
    winformsMap1.CurrentExtent = new RectangleShape(-134, 70, -56, 7);
 
    winformsMap1.Refresh();
}

Can you imagine what the map will look like now? Below is the result. At first it appears like figure 15, and the map changes to figure 8 as you zoom in.


Figure 15. A map of Europe with two ZoomLevels, before zooming in.


Figure 16. The same map with two ZoomLevels, after zooming in.

This completes this scneario. The next thing you might want to do is to make it run on another machine that does not have a developer license. A runtime license is the one we are looking for. Here is the guide to generate a runtime license: http://wiki.thinkgeo.com/wiki/map_suite_runtime_license_guide_for_desktop.

Notes

Because the Desktop Edition uses multi-threading internally for drawing, if you want to change an overlay after the map is initialized, you need to lock the overlay first to avoid threading conflicts. For more information, please have a look at our “How Do I?” sample applications that come with the product.

Summary

You now know the basics of using the Map Suite Map control and be able to get started adding 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:

  1. It is of the utmost importance that the units (feet, meters, decimal degrees, etc.) be set properly for the Map control based on the data.
  2. Shapefiles provide the data used by a Map control to render a map.
  3. A Map is the basic control that contains all of the other objects that are used to tell how the map is to be rendered.
  4. A Map has one-to-many Layers. A Layer correlates one-to-one with a shape file (.shp).
  5. A Layer can have one-to-many ZoomLevels. ZoomLevels help to define ranges (upper and lower) of when a Layer should be shown or hidden.
map_suite_desktop_for_winforms_quick_start_guide.txt · Last modified: 2017/03/15 05:16 by tgwikiupdate