I am working on a UWP navigation app.
Everywhere online there are ways to implement the polyline via c# or code behind, but I want to do it via XAML as adding 10 polylines from codebehind doesn't give much flexibility with events and opacity and Tags and Names.
I tried creating an attached polyline to the mapElement but the issue with the approach is that I'll have to each time remove and recreate the polyline to change colors. More about this here. Also, it's just a pretty way of implementing polyline from code behind.
I added the DataTemplate of the PolyLine in my Page.Resources
like below:
<DataTemplate x:Key="PolylineDataTemplate" x:DataType="polyLineData:IPolylinePath">
<Polyline Points="{x:Bind Polyline,Mode=OneWay}" Fill="{x:Bind PolylineColor,Mode=OneWay}" Tag="{x:Bind PolylineTag,Mode=OneWay}" StrokeThickness="{x:Bind PolylineThinkness}" />
</DataTemplate>`
Where the IPolylinePath is defined as:
public interface IPolylinePath
{
SolidColorBrush PolylineColor { get; set; }
int PolylineThinkness { get; set; }
string PolylineTag { get; set; }
IEnumerable<IBasicGeoposition> PolylinePoints { get; set; }
Geopath PolylineGeopath { get; }
PointCollection Polyline { get; }
}`
My Polyline
property is populated as below:
public PointCollection Polyline
{
get
{
PointCollection returnObject = new PointCollection();
//could have used LINQ but wanted to check if the collection is being populated correctly
foreach (var location in PolylinePoints)
{
returnObject.Add(new Windows.Foundation.Point(location.Latitude, location.Longitude));
}
return returnObject;
}
}
And I am just calling it in the MapItems control like below:
<maps:MapControl x:Name="MyMap" >
<maps:MapItemsControl ItemTemplate="{StaticResource PolylineDataTemplate}" ItemsSource="{x:Bind ViewModel.PolylinePoints}"/>
</maps:MapControl>
The code works perfectly well. Just the polyline is not visible. I thought that it's just small that's why I can't see it. So I increased the size and the distance and it just appears as a small arc on the top left corner (with some spacing) and doesn't get scoped or panned.
Can anyone please help?
Just the polyline is not visible.
Firstly, it seems like you didn't give a Stoke
property for the Polyline
, by default it is null. Your code snippet set color with Fill
property it is not for the color of the line, you may find the value of StrokeThickness
has no influence with the Polyline
and a straight line will not been seen without the Stroke
property. So here the color should be bind to Stroke
property.
it just appears as a small arc on the top left corner
It is because you build points of the Points
property for the Polyline
by code line new Windows.Foundation.Point(location.Latitude, location.Longitude)
.
The latitude and longitude defined the element location on the MapControl
not the application view. In another words, actually you add a GeoPoint
to the PointCollection
, not a Point
. So you may need to transfer the GeoPoint
to Point
by GetOffsetFromLocation(Geopoint, Point)
method.
doesn't get scoped or panned.
For this, the Polyline
is actually a shape not a MapElement
. You should control its MapLocation
by listening the map zoom events. If you want it be pan with the map, you should use MapPolyline
. For sample of this please reference the scenario 2 of the official sample. But MapPolyline
cannot be added directly by binding, only code behind.
A completed simple sample based on yours for testing as follows:
XAML
<Page.Resources>
<DataTemplate x:Key="PolylineDataTemplate" x:DataType="local:PolylinePath">
<Polyline
Points="{x:Bind Polyline}"
Stroke="{x:Bind PolylineColor}"
StrokeThickness="{x:Bind PolylineThinkness}"
Tag="{x:Bind PolylineTag}" />
</DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<maps:MapControl x:Name="MyMap" Loaded="MyMap_Loaded">
<maps:MapItemsControl x:Name="mapitems" ItemTemplate="{StaticResource PolylineDataTemplate}" />
</maps:MapControl>
<Button
x:Name="btnaddpolyline"
Click="btnaddpolyline_Click"
Content="add" />
</Grid>
Code behind:
public sealed partial class MainPage : Page
{
public List<PolylinePath> polylines { get; set; }
Geopoint SeattleGeopoint = new Geopoint(new BasicGeoposition() { Latitude = 47.604, Longitude = -122.329 });
public MainPage()
{
this.InitializeComponent();
}
private void MyMap_Loaded(object sender, RoutedEventArgs e)
{
MyMap.Center = SeattleGeopoint;
MyMap.ZoomLevel = 16;
}
private void btnaddpolyline_Click(object sender, RoutedEventArgs e)
{
polylines = new List<PolylinePath>()
{
new PolylinePath(MyMap)
{
PolylineColor=new SolidColorBrush(Colors.Red),
PolylineThinkness=3,
PolylineTag="testing",
PolylinePoints = new List<BasicGeoposition>()
{
SeattleGeopoint.Position,
new BasicGeoposition()
{
Latitude = SeattleGeopoint.Position.Latitude + 0.003,
Longitude = SeattleGeopoint.Position.Longitude - 0.003
}
}
}
};
mapitems.ItemsSource = polylines;
}
}
public class PolylinePath
{
public PolylinePath(MapControl MyMap)
{
this.MyMap = MyMap;
}
MapControl MyMap;
public SolidColorBrush PolylineColor { get; set; }
public int PolylineThinkness { get; set; }
public string PolylineTag { get; set; }
public IEnumerable<BasicGeoposition> PolylinePoints { get; set; }
public PointCollection Polyline
{
get
{
PointCollection returnObject = new PointCollection();
//could have used LINQ but wanted to check if the collection is being populated correctly
foreach (var location in PolylinePoints)
{
Point actualpoint;
MyMap.GetOffsetFromLocation(new Geopoint(location), out actualpoint);
returnObject.Add(actualpoint);
}
return returnObject;
}
}
}