和传统GIS客户端架构有所不同,BMSL同MapMode的方式来控制Map的一些特征,比如更换地图瓦片数据,限定缩放级别,固定平移范围;甚至是控制鼠标键盘事件导航地图的方式,以及地理坐标与像素坐标的映射等。
Map有属性曰Mode,类型为MapMode。MapMode有子类FlatMapMode,FlatMapMode有子类MercatorMode,MercatorMode有两个子类RoadMode和AerialMode。(关系简单,不再图示)
MercatorMode设置了Web Mercator投影的相关投影,RoadMode和AerialMode分别定了Bing Maps的数据类型,以及导航控件等。比如把Map的Mode设置为空的MercatorMode,即可清除Bing Maps数据,替换其中的TileSource,即可更换底图数据。
若要限制显示范围,则要定制自己的MapMode,比如从RoadMode继承,覆盖GetZoomRange限制缩放级别,覆盖ConstrainView限制平移范围。
下文的示例,大致限定在中国经纬度范围内,缩放级别限定在3和10之间,并把底图数据改变为Google卫星地图以及它的地图注记数据(即那些汉字标绘),如何自定义TileSource请参考《在BMSL中使用Google 地图》。
public class ChinaMode : RoadMode
{
private Range<double> validLatitudeRange = new Range<double>(3.92, 53.51);
private Range<double> validLongitudeRange = new Range<double>(73.60, 135.01);
public ChinaMode()
: base()
{
var tileLayer = (MapTileLayer)this.Content;
tileLayer.TileSources.Clear();
tileLayer.TileSources.Add(new GoogleSatelliteTileSource());
tileLayer.TileSources.Add(new GoogleLabelTileSource());
}
protected override Range<double> GetZoomRange(Location center)
{
return new Range<double>(3, 10);
}
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 > validLongitudeRange.To)
{
newLongitude = validLongitudeRange.To;
}
else if (center.Longitude < validLongitudeRange.From)
{
newLongitude = validLongitudeRange.From;
}
if (center.Latitude > validLatitudeRange.To)
{
newLatitude = validLatitudeRange.To;
}
else if (center.Latitude < validLatitudeRange.From)
{
newLatitude = validLatitudeRange.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;
}
}
定义好之后,调用起来很方便。
XAML:<m:Map x:Name="myMap" CredentialsProvider="Your Key" /> C#:
myMap.Mode = new ChinaMode();
myMap.SetView(new Location(37.5, 104.3), 4);
myMap.MapForeground.TemplateApplied += (s, e) =>
{
myMap.MapForeground.NavigationBar.TemplateApplied += (sender, eventArgs) =>
{
myMap.MapForeground.NavigationBar.HorizontalPanel.Children.Clear();
};
};
限定显示范围内,导航条中的缩放条会自动根据所设置的级别变化,但需要手工屏蔽它自带的Road、Aerial的按钮。上述C#后面的代码作用即此,请注意图中左上角的导航条变化。示例结果图示: http://hi.baidu.com/liongg/blog/item/5724d42a1d048291033bf620.html