I was playing around with porting my Xamarin.Forms app over to .NET MAUI with the release of .NET 7 RC 1, which includes the Map control for MAUI. The app uses open data from my local municipality and shows the different parking zones around town. It also shows additional info like how long you can park and if you are allowed to park there at all. I posted a screenshot to Twitter with my progress, and I was asked if I can share how I created the outlined polygons that made up the parking zones on the map. So, here’s how I did it.
Upgrading to .NET 7
I won’t go into much detail on how I ported my app. I will mention that I had to upgrade my work-in-progress .NET MAUI project to .NET 7. The steps for how to do this is listed in the link I provided at the start, so I won’t go into detail on how to do that here. Link for the lazy.
Then I added a Map
control to my XAML page and gave it an x:Name
of map
. I also wanted the map to start at the location of my municipality, so I used the same code as in the example article and just replaced the coordinates in the Location
property.
Parsing the data
The data set for the parking zones is stored as a GeoJSON file. I load the file from a URL and deserialize the result as a FeatureCollection
, which is the root object of a GeoJSON file.
using var httpClient = new HttpClient();
var stringResult = await httpClient.GetStringAsync(geoJsonUrl);
var jsonResult = JsonConvert.DeserializeObject<FeatureCollection>(stringResult);
Then I iterate over the resulting Features
list from the jsonResult
. Each feature in this case represents a parking zone. Each feature contains a list of coordinates, which makes up the “outline” of the parking zones if you were to draw lines between them.
foreach (var parkingZone in jsonResult.Features)
{
if (parkingZone.Geometry is not Polygon polygon) continue;
var points = polygon.Coordinates.First().Coordinates;
...
}
To represent these parking zones in the map, I create a Polygon
from the Maui.Controls.Maps
namespace. I start by setting the stroke width, the stroke color and the fill color. I want the parking zone to have a distinct “outline”, since these parking zones often are very close to one another and I want them to be distinguishable, so I set the fill color to be just a bit more transparent than the stroke color:
var mapPolygon = new Microsoft.Maui.Controls.Maps.Polygon
{
StrokeWidth = 8,
StrokeColor = Color.Parse("#1BA1E2"),
FillColor = Color.Parse("#881BA1E2"),
ClassId = parkingZone.Properties.ElementAt(4).Value.ToString()
};
I use the ClassId
property to handle click events on individual parking zones, but I won’t cover that in this post.
Now I iterate over the list of coordinates and add it to the mapPolygon
I just created:
foreach (var p in points)
{
mapPolygon.Geopath.Add(new Location(p.Latitude, p.Longitude));
}
Finally, I add the mapPolygon
to the MapElements
property of my map
:
map.MapElements.Add(mapPolygon);
The complete code would look like this:
And that’s how it was done! Like I mentioned, I do have some functionality for when you click a parking zone as well, which will highlight the selected parking zone and show some additional info. If you want to know how I did this, feel free to reach out and I might make a follow-up on this.
Hello , Thanks for the Article.
Is there a way we can have a polygon tap or click on the map ?
Hi Gagan, glad it was helpful!
Yes there is, I didn’t show it in this post but I am doing that in my app. You can add a MapClicked event handler where you check where the user has clicked. You can then loop through your polygons and check if the user has clicked the polygon. See code example below:
var location = e.Location;
bool isPointInPolygon = false;
Feature selectedParkingZone = null;
foreach (var parkingZone in jsonResult.Features)
{
if (parkingZone.Geometry is not Polygon polygon) continue;
var points = polygon.Coordinates.First().Coordinates;
isPointInPolygon = PolygonUtility.PointInPolygon(location.Longitude, location.Latitude, points.ToList());
if (isPointInPolygon)
{
selectedParkingZone = parkingZone;
break;
}
}
The PolygonUtility.PointInPolygon()-method uses this code to determine whether a point is inside a polygon: http://csharphelper.com/howtos/howto_polygon_geometry_point_inside.html
In this case I do a null-check on the selectedParkingZone further down to show an overlay with the parking zone details.
Perfect Andreas ,That really helped and i could handle the clicks now š
Hello, have you tried taking screenshots of the map, from the ScreenShoot() method