如何解决在运行时使用 Xamarin.Forms.Maps 创建折线时如何附加位置?
我正在运行时创建一个 Xamarin.Forms.Maps.Polyline
。鉴于 positions 属性是只读的,我如何动态附加 Polyline.Geopath
?
在运行时创建多段线
按照文档创建多段线:Xamarin.Forms Map Polygons and Polylines。这个链接是一个在代码中固定位置的教程。如何在运行时动态分配位置。
using Xamarin.Forms.Maps;
// ...
Map map = new Map
{
// ...
};
public class MapRoute
{
//[JsonPropertyName("timestamp")]
public long timestamp { get; set; }
//[JsonPropertyName("lat")]
public double lat { get; set; }
//[JsonPropertyName("lng")]
public double lng { get; set; }
public MapRoute(long v1,double v2,double v3)
{
timestamp = v1;
lat = v2;
lng = v3;
}
}
将路由对象序列化为 JsonString。
public void RouteAppend(MapRoute route)
{
JsonString.Append(JsonSerializer.Serialize(route));
JsonString.Append(",");
}
在现实生活中,jsonString 中有 2 个以上的元素(jsonString 中存储了 1000 多个元素)
readonly string jsonString = " [ {\"timestamp\": 1514172600000,\"Lat\": 37.33417925,\"Lng\": -122.04153133}," + "{\"timestamp\": 1514172610000,\"Lat\": 37.33419725,\"Lng\": -122.04151333} ]";
JsonDocument doc;
JsonElement root;
private IList<Position> pos;
doc = Parse(testString);
root = doc.RootElement;
var routes = root.EnumerateArray();
while (routes.MoveNext())
{
var user = routes.Current;
pos.Add(new Position(Convert.Todouble(user.GetProperty("lat")),Convert.Todouble(user.GetProperty("lng"))));
}
最后,有一个包含很多 pos
的列表 Position
,我会将 pos
分配给 Geopath
。不幸的是,这是不允许的。这是一个只读属性:
// instantiate a polyline
polyline polyline = new polyline
{
strokeColor = Color.Blue,strokeWidth = 12,Geopath = pos // It is a readonly property,cannot assign pos to Geopath
}
// add the polyline to the map's MapElements collection
map.MapElements.Add(polyline);
如何解决这个问题?
解决方法
虽然 Polyline.Geopath
是只获取属性,但返回的 IList<Position>
不是只读集合,因此您可以在构造后向其中添加 Position
对象。
因此您可以创建以下工厂方法:
public static class PolylineFactory
{
const string latitudeJsonName = "Lat";
const string longitudeJsonName = "Lng";
public static Polyline FromLatLngJson(string jsonString,float? strokeWidth = default,Color strokeColor = default)
{
using var doc = JsonDocument.Parse(jsonString);
var query = doc.RootElement.EnumerateArray()
// GetProperty performs property name matching as an ordinal,case-sensitive comparison.
.Select(e => new Position(e.GetProperty(latitudeJsonName).GetDouble(),e.GetProperty(longitudeJsonName).GetDouble()));
var polyline = new Polyline();
if (strokeColor != default)
polyline.StrokeColor = strokeColor;
if (strokeWidth != default)
polyline.StrokeWidth = strokeWidth.Value;
foreach (var position in query)
polyline.Geopath.Add(position);
return polyline;
}
}
或者,在 .NET 5 中,JsonSerializer
支持使用单个参数化构造函数反序列化为对象,因此如果您按如下方式稍微修改 MapRoute
类,您可以将 jsonString
反序列化为List<MapRoute>
直接:
public class MapRoute
{
public long timestamp { get; set; }
public double lat { get; set; }
public double lng { get; set; }
public MapRoute(long timestamp,double lat,double lng)
{
// The constructor argument names and property names must match for JsonSerializer to bind to the constructor successfully
this.timestamp = timestamp;
this.lat = lat;
this.lng = lng;
}
}
public static class PolylineFactory
{
public static Polyline FromLatLngJson(string jsonString,Color strokeColor = default)
{
var routes = JsonSerializer.Deserialize<List<MapRoute>>(jsonString,new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
var polyline = new Polyline();
if (strokeColor != default)
polyline.StrokeColor = strokeColor;
if (strokeWidth != default)
polyline.StrokeWidth = strokeWidth.Value;
foreach (var route in routes)
polyline.Geopath.Add(new Position(route.lat,route.lng));
return polyline;
}
}
(在 .NET Core 3.x 中,您需要向 MapRoute
添加一个无参数构造函数,并确保所有属性都是可变的以成功反序列化。)
无论哪种方式,您都可以按如下方式调用工厂方法:
var polyline = PolylineFactory.FromLatLngJson(jsonString,12,Color.Blue);
注意事项:
-
JsonElement.GetProperty()
执行属性名称匹配作为序数,区分大小写的比较,因此您需要传递"Lat"
和"Lng"
而不是 { {1}} 和"lat"
,因为您的"lng"
是 pascal-cased 而不是 camel-cased。如果这是您问题中的一个错误并且您的 JSON 字符串确实是驼峰式大小写,请适当修改
jsonString
和latitudeJsonName
。如果您在获取属性时需要忽略大小写,请参阅 Ignore case when using TryGetProperty。
-
Convert.ToDouble()
使用当前线程文化的格式约定来解释传入的值。在许多欧洲语言环境中,格式化浮点值时使用longitudeJsonName
逗号作为小数点分隔符。由于这与 JSON 标准不一致,因此最好使用内置方法JsonElement.GetDouble()
,它将始终使用正确的小数点分隔符。 -
JsonDocument
是一次性的:这个类利用池内存中的资源来最小化垃圾收集器 (GC) 在高使用率场景中的影响。未能正确处置此对象将导致内存无法返回到池中,这将增加框架各个部分的 GC 影响。
在您的代码中,您不会处理您的
,
,但您应该。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。