在使用包含许多子项的MapLayer时,提高Bing Maps for Silverlight的性能

时间:2011-10-03 15:50:44

标签: .net silverlight performance bing-maps

我有一个使用Bing Maps的Silverlight应用。我需要在地球表面显示约10,000个标记。这些标记是简单的Path个实例,大多数都是相同的形状,尽管它们具有不同的旋转,通过RotateTransform应用。

目前,性能约为6 FPS。我已经尝试了各种方法来改善这种情况,但没有比这更好的了。

逻辑树类似于:

<Map>
  <MapLayer>
    <Path ... />
    <Path ... />
    <Path ... /> <!-- and so on, several thousand times -->

然而,以编程方式添加Path个实例。他们的位置是通过绑定建立的,虽然这些绑定在平移期间不会触发,因此不应该导致我看到的问题。

var path = new Path { /* ... */ };
path.SetBinding(MapLayer.PositionProperty, new Binding("Location")
{
    Source = asset,
    Mode = BindingMode.OneWay
});

我尝试为MapLayer启用GPU加速和位图缓存,并通过观察Process Explorer中的GPU统计信息以及在Silverlight主机中启用FPS计数器/缓存重叠来验证这是否已正确启用。这对FPS几乎没有影响。即使这确实有帮助,也不可能将位图缓存高于某个阈值(2048像素的方块?),因此当您放大一点时,它会回退到软件渲染。

使用dotTrace CPU分析器进一步挖掘,似乎限制因素是重复调用Measure / Arrange。我怀疑这是因为当地图左边的孩子滚动到左边足够远时,他们环绕地球并被移动到最右边(反之亦然),这会导致布局失效,以及任何位图缓存。我认为没有一种简单的方法可以支付这笔罚款。

有没有其他人遇到过这个问题,理想情况下找到了探索的途径?

要尝试的一些随机想法:

  • 直接从MapLayerBase而不是MapLayer导出并自行实施布局算法,绕过MapLayer.PositionProperty依赖项属性并完全支持IProjectable
  • 使用MapItemsControl代替MapLayer进行调查。
  • 将子项目投影到图像上并渲染为更简单的图块。

1 个答案:

答案 0 :(得分:4)

要加快基本的平移和缩放操作,您可以通过继承MapLayer并挂钩到父地图的ViewChange事件来禁用(在鼠标事件期间)富标记图层的渲染,如下所示。我忘记了我最初发现这个的地方,所以如果主人想要获得信用,那么当你的大约10K引脚时,至少保持一致的平移UI体验非常有用。除此之外,我会使用一些自定义聚类,这显然更多地涉及模型层。 HTH

public class OnPanDisableRenderMapLayer : MapLayer
{
    #region Private Properties

    private Visibility _visibility; 

    #endregion 

    #region Constructor 

    ///<summary>
    /// Constructor
    ///</summary>
    public OnPanDisableRenderMapLayer()
        : base()
    {
        this.Loaded += (sender, evt) =>
        {
            Map map = (Map)base.ParentMap;
            map.ViewChangeStart += (s, e) =>
            {
                _visibility = base.Visibility; 

                if (base.Visibility == Visibility.Visible)
                {
                    base.Visibility = Visibility.Collapsed;
                }
            }; 

            map.ViewChangeEnd += (s, e) =>
            {
                base.Visibility = _visibility;
            };
        };
    } 

    #endregion 

    #region Public Properties 

    public Visibility Visibility
    {
        get { return base.Visibility; }
        set
        {
            base.Visibility = value;
            _visibility = value;
        }
    } 

    #endregion
}