学习使用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);
}

最终效果:

首先是在“中国地图”模式下,开启所有内容的显示:

9.1

为了加强对比,这个是在“谷歌卫图”模式下,隐藏所有内容显示(请注意工具条按钮的变化):

9.2

 

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