问题
Im creating UWP app which displays collection of MapIcons on map. MapIcon images are dynamically created from XAML and rendered to bitmap. MapIcon's are updated every few second. There can be around 200 MapIcon on map.
The problem is that my MapIcon update code gets somehow out of sync, MapIcon images are not correct for spesific MapIcon/plane. E.g. some planes get previous plane image etc.
Im storing my MapIcons to separate _planesDictionary (Dictionary<string, MapIcon>
), the idea is to speed up the update process as I hope it is more faster to get map icon from dictionary than from mapControl MapElements list?
My code:
// This is called every few seconds with new planes collection
public async void AddAndUpdatePlanes(IReadOnlyCollection<IRealtimePlane> planes)
{
foreach (var plane in planes)
{
MapIcon foundMapIcon = null;
if(!_planesDictionary.TryGetValue(plane.PlaneId, out foundMapIcon))
{
var planeIcon = new MapIcon
{
Location = new Geopoint(plane.Location),
NormalizedAnchorPoint = new Point(0.5, 0.5),
ZIndex = 10,
CollisionBehaviorDesired = MapElementCollisionBehavior.RemainVisible,
Image = await GetMapIconImage(GetPlaneMarContainer(plane))
};
MapControl.MapElements.Add(planeIcon);
_planesDictionary.Add(plane.PlaneId, planeIcon);
}
else if(foundMapIcon != null)
{
// Update all field to get all markers updated?
foundMapIcon.Location = new Geopoint(plane.Location);
foundMapIcon.NormalizedAnchorPoint = new Point(0.5, 0.5);
foundMapIcon.ZIndex = 10;
foundMapIcon.CollisionBehaviorDesired = MapElementCollisionBehavior.RemainVisible;
foundMapIcon.Image = await GetMapIconImage(GetPlaneMarContainer(plane));
}
}
}
// Get XAML element (grid) which is used to render MapIcon image
private Grid GetPlaneMarContainer(IRealtimePlane plane)
{
PlaneImage.RenderTransformOrigin = new Point(0.5, 0.5);
PlaneImage.RenderTransform = new RotateTransform
{
Angle = plane.Angle
};
PlaneImageText.Text = plane.NumberCode;
return PlaneMarkerContainer;
}
// Convert UIElement MapIcon image source
public async Task<IRandomAccessStreamReference> GetMapIconImage(UIElement uielement)
{
var rtb = new RenderTargetBitmap();
await rtb.RenderAsync(uielement);
var dpi = Windows.Graphics.Display.DisplayInformation.GetForCurrentView().LogicalDpi;
var pixels = (await rtb.GetPixelsAsync()).ToArray();
var stream = new InMemoryRandomAccessStream();
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.BmpEncoderId, stream);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, (uint)rtb.PixelWidth, (uint)rtb.PixelHeight, dpi, dpi, pixels);
await encoder.FlushAsync();
stream.Seek(0);
return RandomAccessStreamReference.CreateFromStream(stream.AsStream().AsRandomAccessStream());
}
This is the XAML which is used to render MapIcon images (this is behind the MapControl).
<Grid x:Name="PlaneMarkerContainer" Width="36" Height="36" Background="Transparent">
<Image x:Name="PlaneImage" Width="36" Height="36" VerticalAlignment="Center" HorizontalAlignment="Center" Source="ms-appx:///Assets/Icons/Plane.png" />
<TextBlock x:Name="PlaneImageText" Text="" FontSize="10" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
More finding: With my PC everything works fine if I have less than 100 MapIcons. With Lumia 950XL, even 50 MapIcon updates is too much. MapIcons (planes) gets wrong images.
UPDATE
This code works completely fine. The issue was in my GetPlaneMarContainer() which had small functionality to pic correct grid. This code is not shown in my example. Somehow I managed to mess up this functionality and it lead my code to not work correctly.
来源:https://stackoverflow.com/questions/36292543/dynamically-update-collection-of-mapicons-update-process-gets-out-of-sync