目前在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系列文章彙總》喲!