====== Map Suite Mobile Quick Start Guide ======
@using ThinkGeo.MapSuite.MvcEdition
@using ThinkGeo.MapSuite.Core
Then, just add the following code to Index.cshtml:
@{
Html.ThinkGeo().Map("Map1", 600, 500)
.MapBackground(new BackgroundLayer(new GeoSolidBrush(GeoColor.FromHtml("#E5E3DF"))))
.CurrentExtent(-131.22, 55.05, -54.03, 16.91)
.MapUnit(GeographyUnit.DecimalDegree)
.CustomOverlays(overlays => overlays.WorldMapKitWmsWebOverlay())
.Render();
}
If you run your project now and view it on a mobile device, such as an Apple iPad®, you will see it looks like this:
{{mvcedition:Mobile_Img09.jpg}}
==== Mobile UI ====
The next step is to make this application's user interface more suitable for use on a mobile device. This section of the Quick Start Guide will show you how to begin by adding a header and footer to your mobile application.
Let's begin by adding a new cshtml file named Header.cshtml in the project's ///Views/Shared// folder.
{{mvcedition:Mobile_Img10.jpg}}
In Header.cshtml, add the following code:
Map Suite Mobile Samples
We can add a Footer in same way. Create a cshtml file called Footer.cshtml in the ///Views/Shared// folder and add the code below:
Now, we need to change the code in _Layout.cshtml to match the following:
@Html.Partial("Header")
@RenderBody()
@Html.Partial("Footer")
Run your application again. Now the result looks like this:
{{mvcedition:Mobile_Img11.jpg}}
=== Fitting the UI to the Screen ===
As you can see in the previous screenshot, it's very important in a mobile application that the application can fill the screen without any blank gaps when using any one of several screen resolutions. To solve this problem and make our mobile UI more responsive, we have to do following things.
1. Change the view page code as follows:
@{
Html.ThinkGeo().Map("Map1",
new System.Web.UI.WebControls.Unit(100,System.Web.UI.WebControls.UnitType.Percentage),
new System.Web.UI.WebControls.Unit(100,System.Web.UI.WebControls.UnitType.Percentage))
.MapBackground(new BackgroundLayer(new GeoSolidBrush(GeoColor.FromHtml("#E5E3DF"))))
.CurrentExtent(-131.22, 55.05, -54.03, 16.91)
.MapUnit(GeographyUnit.DecimalDegree)
.CustomOverlays(overlays => overlays.WorldMapKitWmsWebOverlay())
.Render();
}
The code above sets the width and height of the map to 100%, and also adds the data-role "content" to the container.
2. In order for the jQuery Mobile framework to change the size of the container automatically, we need to add a client page load event to resize the map and make sure it can fully fill the content DIV. In _Layout.cshtml, add the following function:
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
}
else {
window.onload = function () {
oldonload();
func();
}
}
}
In the view page itself, we add the following JavaScript:
addLoadEvent(function () {
Map1.updateSize();
});
3. You may notice that the content DIV might exceed the available screen area once we have applied the Header and Footer view to the application. To resolve this, try adding the code below to _Layout.cshtml:
$(document).ready(function () {
// fix height of content to allow for header & footer
function fixContentHeight() {
var header = $("div[[data-role='header']]:visible");
var footer = $("div[[data-role='footer']]:visible");
var content = $("div[[data-role='content']]:visible:visible");
var viewHeight = $(window).height();
var contentHeight = viewHeight - header.outerHeight() - footer.outerHeight();
if ((content.outerHeight() + header.outerHeight() + footer.outerHeight()) !== viewHeight) {
contentHeight -= (content.outerHeight() - content.height());
content.height(contentHeight);
}
}
$(window).bind("orientationchange resize pageshow", fixContentHeight);
fixContentHeight();
});
And then apply the following CSS (Cascading Style Sheet) script to the page:
==== Display Your Own Data on the Map ====
Now that we have created a simple mobile application that displays a map successfully, we'll show you some additional useful functionality. For example, how to display a particular map extent.
For this example, we need to change the code in the view page as follows:
@{
Html.ThinkGeo().Map("Map1", new System.Web.UI.WebControls.Unit(100, System.Web.UI.WebControls.UnitType.Percentage),
new System.Web.UI.WebControls.Unit(100, System.Web.UI.WebControls.UnitType.Percentage))
.MapBackground(new BackgroundLayer(new GeoSolidBrush(GeoColor.FromHtml("#E5E3DF"))))
.CurrentExtent(-13939426.6371, 6701997.4056, -7812401.86, 2626987.386962)
.MapUnit(GeographyUnit.Meter)
.CustomOverlays(overlays =>
{
PointMarkerStyle pointMarkerStyle = new PointMarkerStyle();
pointMarkerStyle.Popup.ContentHtml = "[[#AREANAME#]]";
pointMarkerStyle.Popup.AutoSize = true;
pointMarkerStyle.Popup.BackgroundColor = GeoColor.FromHtml("#E5E3DF");
pointMarkerStyle.WebImage.ImageOffsetX = -10.5f;
pointMarkerStyle.WebImage.ImageOffsetY = -25f;
ClusterMarkerStyle markerStyle = new ClusterMarkerStyle();
markerStyle.MarkerStyle = pointMarkerStyle;
MarkerZoomLevelSet markerZoomLevelSet = new MarkerZoomLevelSet();
markerZoomLevelSet.ZoomLevel01.CustomMarkerStyle = markerStyle;
markerZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
overlays.WorldMapKitWmsWebOverlay("WorldMapKitOverlay").Projection(WorldMapKitProjection.SphericalMercator).Name("ThinkGeo World Map");
overlays.FeatureSourceMarkerOverlay("markerOverlay").ZoomLevelSet(markerZoomLevelSet);
})
.Render();
}
Once you do that, you will see the following result:
{{mvcedition:Mobile_Img12.jpg}}
You can see that the map extent has been updated to focus in on the United States.
**NOTE**: In this code, we are using ''WorldMapKitWmsWindowsPhoneOverlay'' as the base map, which renders map data from ThinkGeo's mobile-optimized World Map Kit WMS service. As an alternative, you can choose to use Bing Maps, Google Maps or OpenStreetMap as well.
Because we are using the ''WorldMapKitWmsWebOverlay'' in our sample, it was necessary that we set the projection to ''WorldMapKitProjection.SphericalMercator''. It also is important that the ''MapUnit'' property of the ''Map'' object be set to ''GeographyUnit.Meter''. This is because Shapefiles only store binary vector coordinates, which can be in decimal degrees, feet, meters, or numerous other unit systems, and our map has no way to know what the Shapefile's unit of measurement is until we tell it. The correct unit to use is typically found somewhere in the Shapefile's documentation or within its supplemental data file as discussed in the Map Suite MVC Edition Quick Start Guide's [[Map Suite MVC Edition Quick Start Guide#Shapefiles|Shapefiles section]].
==== Querying Data ====
Now we will show you how to perform a spatial query with a specified shapefile. For this example, we will use the Shapefile **cities_a.shp**, which can be found in the //\App_Data// folder of this guide's downloadable sample project.)
{{filehistory:HelloWorld Mobile.zip|Download Sample Code From This Exercise}} //(5.04 MB)//
{{mvcedition:Mobile_Img13.jpg}}
To make this work, we use ''ajaxCallAction'' in the view page to call the controller method. Let's do this step by step:
1. We add a method named ''GetPlaces'' to HomeController, which will return a RectangleShape type result. You'll want to use the code below:
[MapActionFilter]
public RectangleShape GetPlaces(Map map, GeoCollection
**Note**: We need to add a ''MapActionFilter'' attribute to this method to modify the way the action is executed. e.g. Get the necessary parameters, like "map", analyzed based on parameters passed from client side.
2. Add a client side function "findPlaces"
function findPlaces(value, markerImagesIndex) {
if (value == //) {
value = document.getElementById("searchValue").value;
markerImagesIndex = 0;
}
Map1.ajaxCallAction('@ViewContext.RouteData.Values[["Controller"]].ToString()', 'GetPlaces', { category: value, ImagesIndex: markerImagesIndex }, function (result) {
var value = result.get_responseData();
if (value == //) {
alert("No place is found!");
}
var bounds = OpenLayers.Bounds.fromString(value, false);
Map1.zoomToExtent(bounds, false);
});
}
**Note**: Map Suite MVC Edition provides a large number of client APIs that allow us to easily operate the map on the client side, just as we have done on the server side in the above example code. Here, you would use the ''ajaxCallAction'' to call the ''GetPlaces'' method that we just added.
Finally, we will have a project that looks like this on a mobile device or tablet:
{{mvcedition:Mobile_Img14.jpg}}
===== Summary =====
We have introduced the basics of using Map Suite MVC Edition's mobile-friendly UI and a way of 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.
-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.
-MVC Edition provides many client APIs which can operate the map and easily communicate with the server side.
-To display a map that is optimized for mobile devices with the jQuery Mobile Framework (or another mobile UI framework of your preference), we need to control the layout when the page is loaded and resize the map accordingly.