gpt4 book ai didi

c# - 如何提高 Windows Phone 8 map 控制性能

转载 作者:太空宇宙 更新时间:2023-11-03 15:52:28 26 4
gpt4 key购买 nike

在我的 Windows Phone 8 应用程序中,我有 map 控件,其中包含平面(图钉)集合。

Map 在 xaml 中定义如下:

<maps:Map x:Name="Map">
<maptk:MapExtensions.Children>

<maptk:MapItemsControl Name="Planes" ItemTemplate="{StaticResource PlaneTemplate}"/>

</maptk:MapExtensions.Children>
</maps:Map>

Planes MapItemsControl 绑定(bind)到 View 模型中的对象集合 (ObservableCollection),如下所示:

private ObservableCollection<IPlane> _planes;
public ObservableCollection<IPlane> Planes
{
get { return _planes; }
set
{
_planes = value;
NotifyOfPropertyChange(() => Planes);
}
}

public async void GetPlanes()
{
IReadOnlyCollection<IPlane> planes = await realtimePlanes.GetAllPlanesAsync();

foreach (IPlane newPlane in planes)
{
this.Vehicles.Add(newPlane);
}
}

当我调用 GetPlaes() 以从 Web API 获取飞机并更新集合时,整个应用程序会释放几秒钟。通常情况下,Planes 收藏品中大约有 150 - 300 件元素。

我应该如何改进这一点以改善用户体验,消除更新 Planes 集合时的延迟?

我能否以某种方式强制在后台线程(?)中进行此集合更新,或者问题是 map 控制性能?一次绘制所有项目的速度还不够快吗?

更新

这里是更多代码,我的实际应用程序是如何工作的。

只需构建快速而肮脏的测试类/服务来生成测试平面:

public class TestRealtimePlaneService : IRealtimePlaneService
{
private Random random;

public async Task<IEnumerable<IRealtimePlane>> GetAllPlanesAsync()
{
this.random = new Random();

int count = 350;
double x0 = 24.9375;
double y0 = 60.170833;
int radius = 8000;

List<TestRealtimePlane> planes = new List<TestRealtimePlane>();

for (int i = 0; i < count; i++)
{
planes.Add(new TestRealtimePlane() { Location = getLocation(x0, y0, radius), Bearing = 1 });
}

await Task.Delay(5000); // Just to simulate webservice call

return planes;
}

// Taken from http://gis.stackexchange.com/questions/25877/how-to-generate-random-locations-nearby-my-location
public GeoCoordinate getLocation(double x0, double y0, int radius)
{
double radiusInDegrees = radius / 111000f;

double u = this.random.NextDouble();
double v = this.random.NextDouble();
double w = radiusInDegrees * Math.Sqrt(u);
double t = 2 * Math.PI * v;
double x = w * Math.Cos(t);
double y = w * Math.Sin(t);

double new_x = x / Math.Cos(y0);

double foundLongitude = new_x + x0;
double foundLatitude = y + y0;

return new GeoCoordinate(foundLatitude, foundLongitude);
}
}

这是实际的 map 组件

<maps:Map x:Name="Map">
<maptk:MapExtensions.Children>

<maptk:MapItemsControl Name="Planes">
<maptk:MapItemsControl.ItemTemplate>
<DataTemplate>
<maptk:Pushpin GeoCoordinate="{Binding Location}" PositionOrigin="0.5,0.5">
<maptk:Pushpin.Template>
<ControlTemplate TargetType="maptk:Pushpin">
<Grid Width="45" Height="45" Background="Transparent">
<Polygon Fill="Yellow" Points="22,0 34,13, 12,13" Width="45" Height="45" RenderTransformOrigin="0.5,0.5">
<Polygon.RenderTransform>
<RotateTransform CenterX="0.5" CenterY="0.5" Angle="{Binding Bearing}"/>
</Polygon.RenderTransform>
</Polygon>
<Ellipse Fill="Yellow" Stroke="Black" HorizontalAlignment="Center" VerticalAlignment="Center" Width="15" Height="15" StrokeThickness="2" />
</Grid>
</ControlTemplate>
</maptk:Pushpin.Template>
</maptk:Pushpin>
</DataTemplate>
</maptk:MapItemsControl.ItemTemplate>
</maptk:MapItemsControl>

</maptk:MapExtensions.Children>
</maps:Map>

似乎图钉模板对性能的影响也很大。如果我从图钉中删除我自己的控件模板,这会更快一点。

最佳答案

当您使用 WPToolkit 的 MapExtension 显示图钉时,您是在自找麻烦。你会期望 Binding ItemsSource to ObservableCollection<T>为您提供更新 map 的简便方法以及良好流畅的用户体验。

该死的,不!我引用(我自己):

WPToolkit's MapExtensions sucks donkey's arse. It's the kind of a component that makes you question why you started programming in the first place.

可以绑定(bind)ItemsSource收集,但您不能在 XAML 中执行此操作。不,您必须自己挖掘 ItemsSource 并在代码隐藏中明确设置它。

var control = MapExtensions.GetChildren(MyMap).OfType<MapItemsControl>().FirstOrDefault();

还不错,但是等等,还有更多!如果集合中有项目,您不能只用新项目替换它,否则最终会出现异常。不,相反,您必须清除项目,然后一项一项地添加新项目。恩,那就对了。一个接一个!

var planes = (await PlaneRepository.GetAllPlanesAsync()).ToList();

if (Planes.Any())
Planes.Clear();

foreach (var plane in planes)
Planes.Add(plane);

当您更新集合时,UI 会被阻止。没有 Dispatcher , BackgroundWorker也不Task<T>这让你解决了这个问题。

如果有人有任何疑问,请务必指出我哪里做错了。我设置了一个 public GitHub repo (主分支)从中 fork 。

为了使 map 不阻塞,您必须做出一些妥协并完全放弃 MapExtensions。当您创建新的 MapOverlay , 有一个 Pushpin作为内容,并将它们手动添加到您的 map 中,UI 仍然保持响应。

但是也有一个问题。如果您一次添加很多 MapOverlays,那么您仍然会有短暂的卡住。如果您故意延迟添加每个项目(比如 75 毫秒),那么您会获得很好的效果,图钉一个接一个地出现在您的 map 上并且 UI 保持响应。

Task.Factory.StartNew(() =>
{
if (message.Delay != null)
{
foreach (var plane in message.Planes)
{
AddPins(new[] {plane});
Thread.Sleep(message.Delay.Value);
}
}
});

private void AddPins(IEnumerable<IPlane> planes)
{
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
foreach (var plane in planes)
{
var pushpin = new Pushpin
{
Style = Resources["PlaneStyle"] as Style
};

var pushpinOverlay = new MapOverlay
{
GeoCoordinate = plane.Location,
Content = pushpin
};
_pushpinLayer.Add(pushpinOverlay);
}
});
}

响应式 map 示例,使用 MapOverlays,位于 in the same GitHub repo但在 no-map-extensions 分支中。

imgur

这就是您提高 Windows Phone 8 map 控制性能的方式:)。

关于c# - 如何提高 Windows Phone 8 map 控制性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25231758/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com