学习使用Bing Maps Silverlight Control(七):自定义导航工具栏
9 自定义导航工具栏
请先阅读:以下所有对于工具栏的按钮的添加将在这个事件中进行处理。
首先,在页面构造函数中,添加以下事件的处理函数:
public MainPage() { InitializeComponent(); //自定义导航条 map.MapForeground.TemplateApplied += delegate(object sender, EventArgs args) { map.MapForeground.NavigationBar.TemplateApplied += NavigationBar_TemplateApplied; }; }
然后,在相应的处理函数中,对工具栏进行自定义:
void NavigationBar_TemplateApplied(object sender, EventArgs e) { //在这里进行导航工具栏的自定义处理,添加、删除等。。。 }
9.1 实现地图的移动和缩放功能
因为工具栏有两部分,一个是垂直的,一个是水平的,这里先向垂直的工具栏上添加按钮。
对于缩放功能,Bing Maps已经提供了相关的命令,可以直接使用:
void NavigationBar_TemplateApplied(object sender, EventArgs e)
{
//得到地图的导航条 NavigationBar navBar = map.MapForeground.NavigationBar;
//分割线 navBar.VerticalPanel.Children.Add(new CommandSeparator());
//使用ZoomMapCommand命令添加缩放按钮到工具条
CommandButton btnZoomIn = new CommandButton(new ZoomMapCommand(true), "放大", "放大地图"); navBar.VerticalPanel.Children.Add(btnZoomIn); CommandButton btnZoomOut = new CommandButton(new ZoomMapCommand(false), "缩小", "缩小地图"); navBar.VerticalPanel.Children.Add(btnZoomOut);
}
移动命令就需要自定义了,要自定义导航工具栏上的功能,需要实现NavigationBarCommandBase抽象类,并实现相应功能。
因为移动方向有四个,就偷懒写到一个Command里面了。。。用一个枚举区分:
/// <summary> /// 地图移动方向 /// </summary> public enum MoveDirection { 上,下,左,右 }
下面是对NavigationBarCommandBase的实现:
/// <summary> /// 工具条命令:移动地图 /// </summary> class MoveMapCommand : NavigationBarCommandBase { private MoveDirection direction; public MoveMapCommand(MoveDirection direction) { this.direction = direction; } /// <summary> /// 执行命令 /// </summary> /// <param name="map">被执行该命令的工具条控制的地图</param> public override void Execute(MapBase map) { //定义移动位移量,初始均为0 int deltaX = 0; int deltaY = 0; //根据移动方向向移动位移赋值 switch (direction) { case MoveDirection.上: deltaY = -50; break; case MoveDirection.下: deltaY = 50; break; case MoveDirection.左: deltaX = -50; break; case MoveDirection.右: deltaX = 50; break; default: break; } //首先获取当前视图的坐标 Point viewportPoint; if (map.TryLocationToViewportPoint(map.Center, out viewportPoint)) { //将坐标与移动位移量进行相加,对地图视野中心进行调整 viewportPoint.X += deltaX; viewportPoint.Y += deltaY; //将调整后的坐标再设置回地图 Location newCenter; if (map.TryViewportPointToLocation(viewportPoint, out newCenter)) { //前台控件关掉了动画效果,这里再使用时再加上,用完后还原 AnimationLevel al = map.AnimationLevel; map.AnimationLevel = AnimationLevel.Full; map.Center = newCenter; map.AnimationLevel = al;
}
}
}
}
Command类定义好后就可以添加按钮了(以下代码添加至NavigationBar_TemplateApplied函数中):
void NavigationBar_TemplateApplied(object sender, EventArgs e) { //得到地图的导航条 NavigationBar navBar = map.MapForeground.NavigationBar; //分割线 navBar.VerticalPanel.Children.Add(new CommandSeparator()); //使用自定义的MoveMapCommand命令添加移动按钮到工具条 CommandButton btnMoveLeft = new CommandButton(new MoveMapCommand(MoveDirection.左), "左移", "左移地图"); navBar.VerticalPanel.Children.Add(btnMoveLeft); CommandButton btnMoveRight = new CommandButton(new MoveMapCommand(MoveDirection.右), "右移", "右移地图"); navBar.VerticalPanel.Children.Add(btnMoveRight); CommandButton btnMoveUp = new CommandButton(new MoveMapCommand(MoveDirection.上), "上移", "上移地图"); navBar.VerticalPanel.Children.Add(btnMoveUp); CommandButton btnMoveDown = new CommandButton(new MoveMapCommand(MoveDirection.下), "下移", "下移地图"); navBar.VerticalPanel.Children.Add(btnMoveDown); }
等到最后再一起上效果图。
9.2 实现地图模式的更换
这里将向水平向的工具栏上添加按钮,因为原工具栏上已经有了几个地图模式按钮,还是英文的,不好看,首先把它们全部干掉:
navBar.HorizontalPanel.Children.Clear();
然后,开始添加自定义的地图模式按钮,这里是按钮特殊,有预置好的改变地图模式的按钮可以使用,然后直接将需要改变成的地图模式直接new上去就好了:
void NavigationBar_TemplateApplied(object sender, EventArgs e) { //拿到地图的导航条 NavigationBar navBar = map.MapForeground.NavigationBar; //清除横向导航菜单上现有项 navBar.HorizontalPanel.Children.Clear(); //使用ChangeMapModeButton添加地图模式按钮到工具条 ChangeMapModeButton btnRoad = new ChangeMapModeButton(new RoadMode(), "普通地图", "普通地图模式"); navBar.HorizontalPanel.Children.Add(btnRoad); ChangeMapModeButton btnAerial = new ChangeMapModeButton(new AerialMode(true), "卫星地图", "卫星地图模式"); navBar.HorizontalPanel.Children.Add(btnAerial); ChangeMapModeButton btnBirdseye = new ChangeMapModeButton(new BirdseyeMode(), "鸟瞰地图", "鸟瞰地图模式"); navBar.HorizontalPanel.Children.Add(btnBirdseye); ChangeMapModeButton btnStreetside = new ChangeMapModeButton(new StreetsideMode(), "街景地图", "街景地图模式"); navBar.HorizontalPanel.Children.Add(btnStreetside); ChangeMapModeButton btnChina = new ChangeMapModeButton(new ChinaMode(), "中国地图", "自定义的中国地图模式"); navBar.HorizontalPanel.Children.Add(btnChina); ChangeMapModeButton btnGoogle = new ChangeMapModeButton(new GoogleMode(), "谷歌卫图", "谷歌卫星地图模式"); navBar.HorizontalPanel.Children.Add(btnGoogle); }
这里除了控件自带的几个地图模式以外,还添加了两个自定义的地图模式,ChinaMode之前已经做出了实现,就只贴出GoogleMode的代码:
/// <summary> /// 谷歌卫星地图模式 /// </summary> public class GoogleMode : CustomModeBase { public GoogleSatelliteMode() { //初始化谷歌卫星地图瓦片源 GoogleTileSource TileSource = new GoogleTileSource(); //向瓦片图层添加瓦片源 base.TileLayer.TileSources.Add(TileSource); } }
9.3 实现“转到”按钮
自定义一个Command类来实现根据名称转到固定坐标视野的功能,以下是Command类的实现:
/// <summary> /// 工具条命令:转到某处位置 /// </summary> public class GotoCommand : NavigationBarCommandBase { private string PositionName; public GotoCommand(string name) { this.PositionName = name; } public override void Execute(MapBase map) { Location location; double zoomLevel; switch (this.PositionName) { case "北京": default: location = new Location(39.92, 116.46); zoomLevel = 15; break; }//前台控件关掉了动画效果,这里再使用时再加上,用完后还原 AnimationLevel al = map.AnimationLevel; map.AnimationLevel = AnimationLevel.Full; map.SetView(location, zoomLevel); map.AnimationLevel = al;} }
以下是按钮的添加:
void NavigationBar_TemplateApplied(object sender, EventArgs e) { //拿到地图的导航条 NavigationBar navBar = map.MapForeground.NavigationBar; //分割线 navBar.HorizontalPanel.Children.Add(new CommandSeparator()); //使用自定义GotoCommand命令添加“北京”按钮到工具条 CommandButton btnBJ = new CommandButton(new GotoCommand("北京"), "北京", "回到北京"); navBar.HorizontalPanel.Children.Add(btnBJ); }
9.4 实现对地图控件上显示内容的控制
首先是对地图上自带的内容:Logo、比例尺、版权信息的控制,然后再加上之前做的“鹰眼”地图。
因为内容较多,仍然使用一个枚举来决定要控制的内容:
/// <summary> /// 要控制的内容 /// </summary> public enum HideElement { 比例尺,Logo,版权信息,迷你地图 }
下面是对Command类的实现:
/// <summary> /// 工具条命令:显示/隐藏内容 /// </summary> class ToggleHideCommand : NavigationBarCommandBase { private HideElement element; public ToggleHideCommand(HideElement element) { this.element = element; } /// <summary> /// 根据element改变显示/隐藏 /// </summary> /// <param name="map">地图控件</param> /// <param name="visibility">显示/隐藏</param> private void ChangeVisibility(MapBase map, Visibility visibility) { switch (element) { case HideElement.比例尺: map.ScaleVisibility = visibility; break; case HideElement.Logo: map.LogoVisibility = visibility; break; case HideElement.版权信息: map.CopyrightVisibility = visibility; break; case HideElement.迷你地图: map.Children.Where(u => u is Canvas).Select(u => u as Canvas).First().Visibility = visibility; break; default: break; } } public override void Execute(MapBase map) { NavigationBarCommandStatus status = this.GetStatus(map); if (status == NavigationBarCommandStatus.Checked) { ChangeVisibility(map, Visibility.Collapsed); } else if (status == NavigationBarCommandStatus.Normal) { ChangeVisibility(map, Visibility.Visible); } } /// <summary> /// 根据element获取其显示状态 /// </summary> /// <param name="map">地图控件</param> /// <returns>显示状态</returns> private Visibility GetVisibility(MapBase map) { switch (element) { case HideElement.比例尺: return map.ScaleVisibility; case HideElement.Logo: return map.LogoVisibility; case HideElement.版权信息: return map.CopyrightVisibility; case HideElement.迷你地图: return map.Children.Where(u => u is Canvas).Select(u => u as Canvas).First().Visibility; default: return Visibility.Collapsed; } } /// <summary> /// 获取当前按钮其对应的状态,用于在工具条中显示其状态 /// </summary> /// <param name="map">工具条所控制的地图控件</param> /// <returns>返回的状态</returns> public override NavigationBarCommandStatus GetStatus(MapBase map) { NavigationBarCommandStatus status = NavigationBarCommandStatus.Normal; if (GetVisibility(map) == Visibility.Visible) { status = NavigationBarCommandStatus.Checked; } return status; } }
ChangeVisibility和GetVisibility是为了少些代码所封装的自定义函数,这里的重点在于对GetStatus的实现,这个函数的返回值将控制工具条上按钮的状态,是处于选中?还是未选中?状态。
下面向工具栏中添加按钮:
void NavigationBar_TemplateApplied(object sender, EventArgs e) { //拿到地图的导航条 NavigationBar navBar = map.MapForeground.NavigationBar; //分割线 navBar.HorizontalPanel.Children.Add(new CommandSeparator()); //使用自定义ToggleHideCommand命令添加“北京”按钮到工具条(注:这个按钮有状态) CommandToggleButton btnScale = new CommandToggleButton (new ToggleHideCommand(HideElement.比例尺), "比例尺", "显示/隐藏比例尺"); navBar.HorizontalPanel.Children.Add(btnScale); CommandToggleButton btnLogo = new CommandToggleButton
(new ToggleHideCommand(HideElement.Logo), "Logo", "显示/隐藏Logo"); navBar.HorizontalPanel.Children.Add(btnLogo); CommandToggleButton btnCopyright = new CommandToggleButton
(new ToggleHideCommand(HideElement.版权信息), "版权信息", "显示/隐藏版权信息"); navBar.HorizontalPanel.Children.Add(btnCopyright); CommandToggleButton btnMiniMap = new CommandToggleButton
(new ToggleHideCommand(HideElement.迷你地图), "迷你地图", "显示/隐藏迷你地图"); navBar.HorizontalPanel.Children.Add(btnMiniMap); }
最终效果:
首先是在“中国地图”模式下,开启所有内容的显示:
为了加强对比,这个是在“谷歌卫图”模式下,隐藏所有内容显示(请注意工具条按钮的变化):
输了你,赢了世界又如何...