0%

  在Bing Maps Silverlight Control中以及为我们提供了地图图钉控件Pushpin,我曾经在《使用图钉层(Pushpin layer)及地图图层(MapLayer)》一文中介绍过他的使用方法,本篇主要介绍如何自定义图钉标注控件以及对他的一些扩展,比如实现图钉的动态ToolPanel。

  关于图钉的UI外观的设计这里就不详细介绍了,通过Blend可以快速的构建UI界面。首先介绍下我的实现思想,通过Path构建图钉标注控件的UI外观,控件整体布局使用Grid布局,分别在Grid容器里设计好图钉UI外观效果和需要动态提示的ToolPanel(使用Border布局设计),默认将ToolPanel隐藏,在后台代码中通过鼠标事件进行控制其是否出现;另外还布局了一个TextBlock控件,用于出现图钉标注上的内容。下面是定义好的图钉风格的样式:

自定义图钉样式

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       接下来要做的就是实现图标注控件的定义以及动态控制ToolPanel控件的显示与否了,主要思路就是通过引用上面定义的样式,以模板的方式从样式里获取到相应的控件元素进行动态控制,详细见如下代码: ![复制代码](https://common.cnblogs.com/images/copycode.gif) ///  /// 自定义图钉控件///  public class PushPinControl : ContentControl {    private string Text;public PushPinControl(String text)     {        //设置图钉标注控件的标注内容         this.Text \= text \== "" ? "M" : text;         DefaultStyleKey \= typeof(PushPinControl);        //为当前对象引用样式,从全局资源里读取         this.Style \= Application.Current.Resources\["PushpinStyle"\] as Style;     }public override void OnApplyTemplate()     {        base.OnApplyTemplate();//从样式模板中获取TextBlock控件         var textBlock \= GetTemplateChild("txtTitle") as TextBlock;         textBlock.Text \= this.Text;        //从样式模板中获取ToolPanel(既Border布局实现的,详细见样式的定义)控件         var ToolPanelBorder \= GetTemplateChild("ToolPanel") as Border;        //通过事件动态控制ToolPanel的显示和隐藏         this.MouseEnter += (mes, meo) \=> { ToolPanelBorder.Visibility \= Visibility.Visible; };        this.MouseLeave += (mls, mlo) \=> { ToolPanelBorder.Visibility \= Visibility.Collapsed; };     } } ![复制代码](https://common.cnblogs.com/images/copycode.gif)   到这里就成功的完成了图钉标注控件的自定义了,接下来看看如何使用这个自定义的图钉标注控件,详见如下代码块: ![复制代码](https://common.cnblogs.com/images/copycode.gif) private void AddPushPin() {    //添加Bing Maps Silverlight Control自带的图钉    //var pushpin = new Pushpin();    //pushpin.Location = new Location(29.5076372217973, 106.489384971208);    //添加自定义的图钉     var pushpin \= new PushPinControl("D");     MapLayer.AddChild(pushpin, new Location(29.5076372217973, 106.489384971208)); } ![复制代码](https://common.cnblogs.com/images/copycode.gif)        ![](https://images.cnblogs.com/cnblogs_com/beniao/BingMaps/PushpinDisplay.jpg)   或许会有人问道,如何动态的实现ToolPanel里显示的内容?要实现这个功能也是非常简单的,首先我们来分析下上面定义的样式里对ToolPanel部分的定义: ![复制代码](https://common.cnblogs.com/images/copycode.gif)                                                                                                                                                                      ![复制代码](https://common.cnblogs.com/images/copycode.gif)   使用了Border进行圆角布局,在其内部通过StackPanel垂直布局实现了ToolPanel的的标题和内容两大部分,内容部分并通过Border进行设计,取名为ContentBorder,这是为了实现动态呈现显示内容而设计,整体Border通过TranslateTransform进行一个偏移的处理,也就是让ToolPanel始终显示在图钉标注的右边相应的位置,详细见本文前面提供的截图。   从上面的实现知道ToolPanel是在鼠标的MouseEnter事件执行的时候才会显示的,当鼠标离开就会将其可见性设置为隐藏。了解了这个原理后就可以想到,是否可以从MouseEnter事件中通过某种方法去处理?事件是个非常强大的技术点,这里我们就可以通过事件,将显示内容的Border容器派发处理,通过事件的监听来动态更新其显示内容。首先需要扩展一个事件类: ![复制代码](https://common.cnblogs.com/images/copycode.gif) public delegate void PushpinContentChangedHandler(object sender,PushpinContentChangedEvantAgrs e);public class PushpinContentChangedEvantAgrs : EventArgs {    public Border ContentBorder { get; set; }public PushpinContentChangedEvantAgrs() { }public PushpinContentChangedEvantAgrs(Border ContentBorder)     {        this.ContentBorder \= ContentBorder;     } } ![复制代码](https://common.cnblogs.com/images/copycode.gif)      接下来为自定义的图钉标注类定义一个事件,事件类型就为上面所定义好的委托类型,传递的事件为PushpinContentChangedEventArgs. ![复制代码](https://common.cnblogs.com/images/copycode.gif) ///  /// 自定义图钉控件///  public class PushPinControl : ContentControl {    public event PushpinContentChangedHandler ContentChangedEvent; ![复制代码](https://common.cnblogs.com/images/copycode.gif)     现在需要做的就是在当前对象的MouseEnter事件中去触发这个事件,将样式里所定义好的用于显示内容的Border对象获取出来,通过事件参数传递派发出去,让事件监听段可以通过该事件获取事件参数进行ToolPanel内容的呈现更新。所有我们需要改写PushPinControl的OnApplyTemplate方法: ![复制代码](https://common.cnblogs.com/images/copycode.gif) public override void OnApplyTemplate() {    base.OnApplyTemplate();//从样式模板中获取TextBlock控件     var textBlock \= GetTemplateChild("txtTitle") as TextBlock;     textBlock.Text \= this.Text;    //从样式模板中获取ToolPanel(既Border布局实现的,详细见样式的定义)控件     var ToolPanelBorder \= GetTemplateChild("ToolPanel") as Border;    //获取内容Border对象,通过事件将该对象派发出去,在使用段可以通过监听这个事件而获取到内容Border     var ContentBorder \= GetTemplateChild("ContentBorder") as Border;    //通过事件动态控制ToolPanel的显示和隐藏     this.MouseEnter += (mes, meo) \=>     {          ToolPanelBorder.Visibility \= Visibility.Visible;          if (ContentChangedEvent != null)         {             ContentChangedEvent(this, new PushpinContentChangedEvantAgrs(ContentBorder));         }     };    this.MouseLeave += (mls, mlo) \=> { ToolPanelBorder.Visibility \= Visibility.Collapsed; }; } ![复制代码](https://common.cnblogs.com/images/copycode.gif)    通过ContentChangedEvent事件的监听动态的去改变ToolPanel里的显示内容就可以达到我们的目的了,比如我们动态的将ToolPanel里的显示内容更改为一张图片,上面使用自定义图钉标注的代码将变成下面这样的。 ![复制代码](https://common.cnblogs.com/images/copycode.gif) private void AddPushPin() {    //添加Bing Maps Silverlight Control自带的图钉    //var pushpin = new Pushpin();    //pushpin.Location = new Location(29.5076372217973, 106.489384971208);    //添加自定义的图钉     var pushpin \= new PushPinControl("D");     pushpin.ContentChangedEvent += (sender, o) \=>        {            //构造Image对象 用于显示在ToolPanel中             var image \= new Image { Width \= 100, Height \= 100, Margin \= new Thickness(8) };             image.Source \= new BitmapImage(new Uri("Resources/Smbecker.png", UriKind.RelativeOrAbsolute));             Border border \= o.ContentBorder;             border.Child  \= image;         };     MapLayer.AddChild(pushpin, new Location(29.5076372217973, 106.489384971208)); } ![复制代码](https://common.cnblogs.com/images/copycode.gif)         ![](https://images.cnblogs.com/cnblogs_com/beniao/BingMaps/ToolPanelImage.jpg)    之前有网友问到如何实现可拖拽的图钉标注控件,鉴于篇幅的原因这里就不做介绍,不清楚的朋友可以留言讨论。本篇就介绍到这里,欢迎大家前来交流、讨论、拍砖。   **更多学习资料:**   MSDN:[http://msdn.microsoft.com/en-us/library/ee681890.aspx](http://msdn.microsoft.com/en-us/library/ee681890.aspx)   官方:[http://www.microsoft.com/maps](http://www.microsoft.com/maps)   中国Bing Maps:[http://cn.bing.com/ditu/](http://cn.bing.com/ditu/)   官方SDK:[http://www.microsoft.com/maps/isdk/silverlight/](http://www.microsoft.com/maps/isdk/silverlight/)