While thinking about an article topic for Xamarin UI July, I reached for an article idea which I had in my backlog a while now – highlighting countries in the Xamarin.Forms map control. This functionality can be useful when your app is showing some data filtered by country or when the user provides their country during registration. Providing visual feedback to the user’s selection makes the app come alive.
Getting the data
Each country on the world map is a set of polygonal areas (a single polygon is enough for most, but countries like Japan definitely need more than one). We need to find a data source with the approximate boundary of these areas so that we can display them on the map. Also – we need this in a format which is easily parseable in a Xamarin app.
Chances are you have already encountered the JSON format, which is today the de-facto default for lightweight data transfer. It turns out, there is a variant of the JSON format specifically suited for geographical data – GeoJSON. While it is fully JSON compatible, so we could just read it with JSON.NET, there is also a wonderful open-source library which makes working with this format a breeze – GeoJSON.Net.
With the format chosen, it’s time to find a data source. Luckily, open-source is here to help us once more! This GitHub repository contains a lightweight (251 KB) GeoJSON file with rough geometries of all countries!
Perfect, we are ready to dive into code!
First, we will build a simple user interface on which we can demonstrate the country highlighting:
Nothing too fancy, just a simple
ListView of countries and a map control below. Xamarin.Forms Map can be included in your project by following a few simple steps detailed in the documentation. Make sure to note that
Map control is no longer part of the default Xamarin.Forms NuGet package and it is provided separately as a Xamarin.Forms.Maps NuGet package.
The data-binding portions of the UI will be provided by the code-behind later in this article.
Map highlighting support
The built-in Xamarin.Forms map control does not have support for polygon drawing on top of the map. This is a functionality we definitely require and we will have to implement it ourselves.
First off, we create a set of support classes to describe a polygon, and highlight on the map:
MapHighlight class supports multiple polygons, in line with the requirements of some countries as mentioned above.
To introduce highlighting functionality to the map, we create a new
HighlightableMap control by deriving from
We start our platform-specific renderers with UWP. When the
Highlight property is updated, we clear the existing
MapElements from the native map control and add polygons from the current
MapHighlight instance. UWP
MapPolygon includes support for fill and stroke color and stroke thickness. We use the
ToWindowsColor() extension method to convert Xamarin.Forms color to UWP’s
The Android map renderer is pretty straightforward and similar to UWP. The key difference here is that map initialization is finished asynchronously so we need to wait for it to complete to update the highlight in the first place.
iOS API for map polygons is probably the least pleasant of the three platforms. Displaying geometry on top of the map is done using a concept of “overlays”, which however do not have their visual properties embedded. Those have to be provided in
OverlayRenderer delegate. We handle this in the
OverlayRendererHandler method. As we need a reference to the instance of
MapHighlight his is currently being drawn, we store it in a field.
Now with the map control ready to use, we can write the main logic of our application. For the sake of simplicity, I will put my code into the code-behind of our page, but it would be probably better suited in a view model.
To represent a country, we create a simple POCO class. Note the code uses the cool new tuple-initialization in its constructor.
When the page loads, we need to initialize the list of countries first. The
ReadCountryGeoJson() method returns the contents of the
countries.geo.json file. In my case, I added the file as an embedded resource to the project.
The country data are parsed to a
FeatureCollection , which is a specialized type provided with GeoJSON.Net. This gives us easy access to the
Id field and
name property of the features.
SelectedItem property of our
ListView is two-way bound to
SelectedCountry property. Let’s implement that now:
Finally, we need to implement the
HighlightCountry method. Based on the country selection we find the GeoJSON.Net feature for it and check if it is a single- or multi-polygon area. We create appropriate
MapPolygon instances based on this and then instantiate the
To make sure the user actually sees the highlighted area, we are also calculating the minimum and maximum latitude and longitude of the area, and its center. The call of the
MoveToRegion method will bring the area into view. Note I am multiplying the area size by 1.2, just to show a bit of margin around the highlight as well.
Here is our sample app running on UWP, Android and iOS.
Full source code for this article along with the sample application is available on my GitHub.
We have shown how to add custom behavior to the map control in Xamarin.Forms and implemented a reusable highlighting feature with adjustable visuals. While we demonstrated this on country highlighting, it could be utilized for many other purposes as well.