学习使用Bing Maps Silverlight Control(五):离线使用和自定义地图模式

6 离线使用

在笔记第一部分的时候就提到如果要使用Bing Maps Silverlight Control 进行开发,需要申请一个key,不让会显示一个错误提示出来。但是在实际开发或使用过程中,使用环境和地图数据可能不是在线的,但控件因为验证失败仍然会显示以下内容:

6.1

如何去掉这个提示?最简单的方式就是自己扩展一个Map控件,在其构造方法中将错误提示层给干掉,然后再项目中使用自定义的Map控件,大致可以如下实现:

首先,自定义一个类型,继承自Map类:

namespace CustomBingMaps
{
    public class OfflineMap : Map
    {
        public OfflineMap()
            : base()
        {
            base.LoadingError += (sender, e) =>
            {
                base.RootLayer.Children.RemoveAt(5);
            };
        }
    }
}

然后,在前台引用刚才的自定义类型的命名空间,就可以使用这个扩展的OfflineMap控件了:

<UserControl x:Class="xwgmap_sl_client.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:m="clr-namespace:Microsoft.Maps.MapControl;assembly=Microsoft.Maps.MapControl"
    xmlns:c="clr-namespace:CustomBingMaps"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
    <Grid x:Name="LayoutRoot" Background="White">
        <c:OfflineMap Name="map" LogoVisibility="Collapsed" CopyrightVisibility="Collapsed"></c:OfflineMap>
    </Grid>
</UserControl>

这样在离线使用控件的时候就不会再显示错误了。

(以上方法转载自:http://www.cnblogs.com/beniao/archive/2010/05/28/1745896.html,相关原理没有转载,有兴趣的话可以去原博客查看。)

7 自定义显示范围

如果使用自己的地图数据进行加载使用,一般来说相对于全球只会覆盖一部分的地区,剩下的地区都是空白,还有地图数据不一定对应所有的缩放级别都有,如何限制可以查看的地图范围和缩放级别呢?答案就是自定义MapMode。

在这里,自定义MapMode来限制视野范围主要是要重写两个方法:GetZoomRange 和 ConstrainView,前者用来限制缩放范围,后者则将经纬度和缩放进行统一限制。

还有一个问题需要说明,Bing Maps自带的RoadMode(普通地图)和AerialMode(卫星地图)都是继承自MercatorMode(墨卡托投影),所以这里也将直接从MercatorMode派生出自定义MapMode(当然也可以扩展前两个模式)。但是MercatorMode没有任何TileSource,所以如果直接显示出来就什么也看不到了,所以还要再给自定义类型加上Tile图层。

首先是自定义了一个必应地图(简体中文)的TileSource类:

/// <summary>
/// 必应地图的Tile系统
/// </summary>
public class BingDituTileSource : LocationRectTileSource
{
    public BingDituTileSource()
    {
        //设定瓦片源Tile系统的Uri格式,其中的{quadkey}就是每个瓦片quadkey的对应位置
        //这里使用的是必应地图(简体中文)的Tile系统
        UriFormat = "http://r0.tiles.ditu.live.com/tiles/r{quadkey}.png?g=99&mkt=zh-cn";
    }
}

下面就开始自定义ChinaMode类,为了方便以后的扩展,这里将对MercatorMode的扩展提取成CustomModeBase,在此基础上再扩展出ChinaMode。所以首先是CustomModeBase的代码:

/// <summary>
/// 自定义地图基类,实现了视野范围的限制和自定义瓦片源。
/// 使用前请初始化:
/// TileLayer(瓦片源)
/// LatitudeRange(经度范围)
/// LongitudeRange(纬度范围)
/// MapZoomRange(缩放范围)
/// </summary>
public class CustomModeBase : MercatorMode
{
    /// <summary>
    /// 用于呈现Tile层
    /// </summary>
    public override UIElement Content
    {
        get
        {
            return this.TileLayer;
        }
    }

    /// <summary>
    /// 存储Tile图层
    /// </summary>
    public MapTileLayer TileLayer;

    /// <summary>
    /// 纬度范围
    /// </summary>
    public Range<double> LatitudeRange;

    /// <summary>
    /// 经度范围
    /// </summary>
    public Range<double> LongitudeRange;

    /// <summary>
    /// 缩放范围
    /// </summary>
    public Range<double> MapZoomRange;

    /// <summary>
    /// 初始化基类字段
    /// </summary>
    public CustomModeBase()
    {
        this.TileLayer = new MapTileLayer();
        this.LatitudeRange = new Range<double>(-90, 90);
        this.LongitudeRange = new Range<double>(-180, 180);
        this.MapZoomRange = new Range<double>(1, 20);
    }

    /// <summary>
    /// 缩放范围
    /// </summary>
    /// <param name="center"></param>
    /// <returns></returns>
    protected override Range<double> GetZoomRange(Location center)
    {
        return MapZoomRange;
    }

    //当地图视野改变时将调用该函数进行处理(即可达到限制地图范围的效果)
    public override bool ConstrainView(Location center, ref double zoomLevel, ref double heading, ref double pitch)
    {
        bool isChanged = base.ConstrainView(center, ref zoomLevel, ref heading, ref pitch);

        double newLatitude = center.Latitude;
        double newLongitude = center.Longitude;

        //如果视野纬度超出范围,则将视野范围限制在边界
        if (center.Longitude > LongitudeRange.To)
        {
            newLongitude = LongitudeRange.To;
        }
        else if (center.Longitude < LongitudeRange.From)
        {
            newLongitude = LongitudeRange.From;
        }

        //如果视野经度超出范围,则将视野范围限制在边界
        if (center.Latitude > LatitudeRange.To)
        {
            newLatitude = LatitudeRange.To;
        }
        else if (center.Latitude < LatitudeRange.From)
        {
            newLatitude = LatitudeRange.From;
        }

        //设置新的地图视野(限制在范围中)
        if (newLatitude != center.Latitude || newLongitude != center.Longitude)
        {
            center.Latitude = newLatitude;
            center.Longitude = newLongitude;
            isChanged = true;
        }

        //设置新的地图缩放级别(限制在范围中)
        Range<double> range = GetZoomRange(center);
        if (zoomLevel > range.To)
        {
            zoomLevel = range.To;
            isChanged = true;
        }
        else if (zoomLevel < range.From)
        {
            zoomLevel = range.From;
            isChanged = true;
        }

        return isChanged;
    }
}

然后再新建ChinaMode类,继承自CustomModeBase:

/// <summary>
/// 中国地图模式
/// </summary>
public class ChinaMode : CustomModeBase
{
    public ChinaMode()
    {
        //初始化必应地图(简体中文)瓦片源
         BingDituTileSource TileSource = new BingDituTileSource();

        //向瓦片图层添加瓦片源
         base.TileLayer.TileSources.Add(TileSource);

        //向地图添加限制范围
         base.LatitudeRange = new Range<double>(0, 50);
        base.LongitudeRange = new Range<double>(70, 140);
        base.MapZoomRange = new Range<double>(5, 10);
    }
}

需要说明的是:这里经纬度的限制范围并不是边界范围,而是视野中心(Center)的边界,可能是为了方便适应不同的分辨率和缩放级别吧,所以处理经纬度边界的时候需要比较谨慎。缩放的级别就是可以缩放的级别,这个没有问题,缩放级别设定后,界面工具条上的缩放工具栏也会自动的做出相应的改变。

如何使用MapMode就比较简单了,比如在后台代码进行改变:

public MainPage()
{
    InitializeComponent();

    map.Mode = new ChinaMode();
}

也可以在前台直接设置Mode属性:

<c:OfflineMap Name="map"CopyrightVisibility="Collapsed" LogoVisibility="Collapsed" ScaleVisibility="Collapsed">
    <c:OfflineMap.Mode>
        <c:ChinaMode></c:ChinaMode>
    </c:OfflineMap.Mode>
</c:OfflineMap>

这时可以通过设计视图的预览直接看到效果。

最终效果(各种限制无法在截图中展示,请自行体验。。。):

7.1

(以上内容参考自:http://msdn.microsoft.com/en-us/library/ee681896.aspx,更多内容请参阅msdn。)

posted @ 2013-04-18 17:24  不是豆豆  阅读(972)  评论(0编辑  收藏  举报
友情链接:迷途