目前在Bing Maps Silverlight Control中并没有提供可拖放的图钉(Pushpin)控件,其强大、灵活的架构设计为开发者提供了非常强大的扩展支持,要实现图钉控件的可拖放性可以自己动手进行扩展实现。
System.Windows.DependencyObject
System.Windows.UIElement
System.Windows.FrameworkElement
System.Windows.Controls.Control
System.Windows.Controls.ContentControl
Microsoft.Maps.MapControl.Pushpin
在扩展Pushpin之前先了解下Pushpin控件在Bing Maps Silverlight Control中的结构设计(如上代码结构),Pushpin是通过扩展Silverlight中的ContentControl控件开发而成,并加入了了定位坐标(Location)属性及其它相关的属性、字段。鉴于图钉的定位主要会用到Location属性,故本篇只提出此属性,其他的字段属性的详细在后续的相关博文里介绍。
在使用Bing Maps Silverlight Control开发中,使用内置提供的图钉(不提供可拖放操作功能)主要有两种方式,分别是后台代码动态创建后作为子对象添加到MapLayer上,另外一种方式则是直接在XAML代码里直接配置。如下代码块:
<m:Pushpin Location="29.5076372217973, 106.489384971208" Content="D"></m:Pushpin>
</m:Map>
通过上代码段的结构很清晰的知道,图钉控件(Pushpin)的父节点为MapLayer对象,在MapLayer中有一个属性ParentMap可以得到当前MapLayer对象属于那一个Map控件对象,于是在图钉对象上既然能够获取到直接所属的Map控件,也就是说在图钉控件里是可以对Map控件进行动态控制的。
接下来就通过自定义一个可拖拽的图钉类来对Bing Maps Silverlight Control中内置的图钉控件进行扩展,可以通过如下的代码来实现一个最基本的可拖放的图钉的结构。
{
/// <summary>
/// 是否正在拖放
/// </summary>
private bool IsDragging = false;
/// <summary>
/// 鼠标拖放
/// </summary>
private EventHandler<MapMouseDragEventArgs> MapMouseDragHandler;
/// <summary>
/// 鼠标左键弹起
/// </summary>
private MouseButtonEventHandler MapMouseLeftButtonUpHandler;
/// <summary>
/// 鼠标移动
/// </summary>
private MouseEventHandler MapMouseMoveHandler;
}
实际上要实现一个对象的可拖拽是非常简单的,不清楚的可以访问我的另一篇博文《Silverlight & Blend动画设计系列八:拖放(Drag-Drop)操作与拖放行为(DragBehavior)》进行了解。简单的说实现拖放操作就是通过鼠标事件动态改变对象的位置,只不过在Bing Maps Silverlight Control中要实现图钉控件的操作不能像传统的实现元素对象的操作那么去处理,这主要是由于地图控件(Map)中做了一些相关的处理的原因。
鉴于这种种原因就不得不实现对象本身的行为特性的功能转移到Map控件的事件处理函数中去实现,Bing Maps Silverlight Control中的Map控件有一个名为MousePan的事件,专门用来处理鼠标拖放操作行为,其定义为如下结构:
public override event EventHandler<MapMouseDragEventArgs> MousePan;
另外还有一个事件就是MouseMove,它被定义为Bing Maps Silverlignt Control中的Map控件的事件,专门用来处理鼠标移动的相关操作行为,其功能作用非常强大。
public abstract event MouseEventHandler MouseMove;
有了以上两个事件的支持我们的自定义可拖放的图钉控件就可以面世出生了。下面为完整的可拖放图钉控件的代码:
/// 功能描述:自定义扩展图钉类,实现可拖拽图钉。
/// 编 写:Beniao
/// 时 间:2010年5月31日22:37:46
/// </summary>
public class DraggablePushpin : Microsoft.Maps.MapControl.Pushpin
{
/// <summary>
/// 是否正在拖放
/// </summary>
private bool IsDragging = false;
/// <summary>
/// 鼠标拖放
/// </summary>
private EventHandler<MapMouseDragEventArgs> MapMouseDragHandler;
/// <summary>
/// 鼠标左键弹起
/// </summary>
private MouseButtonEventHandler MapMouseLeftButtonUpHandler;
/// <summary>
/// 鼠标移动
/// </summary>
private MouseEventHandler MapMouseMoveHandler;
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
//因为图钉是添加在MapLayer上的
var parentLayer = this.Parent as MapLayer;
if (parentLayer != null)
{
//MapLayer是Map的一个子对象
var parentMap = parentLayer.ParentMap;
if (parentMap != null)
{
if (this.MapMouseDragHandler == null)
{
this.MapMouseDragHandler = new EventHandler<MapMouseDragEventArgs>(ParnetMap_MousePan);
parentMap.MousePan += this.MapMouseDragHandler;
}
if (this.MapMouseLeftButtonUpHandler == null)
{
this.MapMouseLeftButtonUpHandler = new MouseButtonEventHandler(PrentMap_MouseLeftButtonUp);
parentMap.MouseLeftButtonUp += this.MapMouseLeftButtonUpHandler;
}
if (this.MapMouseMoveHandler == null)
{
this.MapMouseMoveHandler = new MouseEventHandler(PrentMap_MouseMove);
parentMap.MouseMove += this.MapMouseMoveHandler;
}
}
}
this.IsDragging = true;
base.OnMouseLeftButtonDown(e);
}
private void ParnetMap_MousePan(object sender, MapMouseDragEventArgs e)
{
if (this.IsDragging)
{
e.Handled = true;
}
}
private void PrentMap_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
this.IsDragging = false;
}
private void PrentMap_MouseMove(object sender, MouseEventArgs e)
{
var map = sender as Map;
if (this.IsDragging)
{
var mousePosition = e.GetPosition(map);
var geoPosition = map.ViewportPointToLocation(mousePosition);
this.Location = geoPosition;
}
}
}
通过扩展后的图钉控件(DraggablePushpin)就是一个完整的可支持鼠标拖放的图钉控件,其使用和内置的原始控件一样简单,如下代码实现了动态添加500个图钉在MapLayer上。
{
for (int i = 1; i < 501; i++)
{
MapLayer.AddChild(new DraggablePushpin()
}
}
最终的运行效果如下图(图中的图钉部分是通过鼠标拖放过后的)所示:
注:看了本文不要忘记看本系列所有文章《【Silverlight】Bing Maps系列文章汇总》哟!