本文主要內容是講述如何建立基於 Windows Universal App 的Windows 10 3D地圖應用,涉及的Windows 10新特性包括 Bing Maps 控件、Compiled data bindings (x:Bind),SplitView 和Hamburger。git
本文中的示例源代碼已在github 上共享( https://github.com/gaoxuesong/navigado )。github
在 Universal Windows App 中使用必應地圖須要從 Bing Maps Developer Center 獲取地圖驗證密鑰,並將其添加到應用中。windows
建立新密鑰:api
將建立的密鑰複製到安全位置,在下面的步驟中咱們會將其加入到Universal Windows App 中。瀏覽器
打開 Visual Studio 2015(目前最新版爲 Visual Studio 2015 RC),選擇File > New Project。 安全
展開Installed > Templates ,選擇 Windows Universal > Blank App ( Windows Universal),以下圖所示。app
設定工程的名稱即在 Name 中輸入應用的名稱,本例爲"navigado"。Navigado是世界語導航的意思。dom
設定工程保存的目錄,即在 Location 中設定工程保存的目錄。async
點擊 OK 即建立新的Windows 10 Universal App。ide
在 XAML 頁面或代碼中,MapControl 須要 Windows.UI.Xaml.Controls.Maps 命名空間的命名空間聲明。
本例中是手動將 MapControl 添加到 MainPage.XAML 頁面,並在該頁面頂部手動添加命名空間聲明:
xmlns:Maps="using:Windows.UI.Xaml.Controls.Maps"
若要在你的 Universal Windows App 中使用 MapControl 和地圖服務 (Windows.Services.Maps),則須要地圖驗證密鑰。將該密鑰添加到地圖控件和地圖服務對象(若是適用)。
若要驗證 MapControl,請使用該密鑰來設置 MapServiceToken 屬性值。你能夠在代碼中設置該屬性,也能夠在 XAML 標記中設置。
在本例中採用 Compiled data bindings (x:Bind) 的方式將必應地圖的密鑰綁定至 XAML 文件中的 MapControl,代碼以下:
File: MainPage.xaml
<Maps:MapControl
x:Name="myMapControl"
MapServiceToken="{x:Bind BingMapsToken, Mode=OneWay}"
Loaded="MapControlLoaded"/>
在 MainPage.xaml.cs中的 MainPage 類中設定 BingMapsToke 的值,BingMapsToken的值便是在第一步驟中獲取的 Bing Maps的密鑰。代碼以下:
File: MainPage.xaml.cs
private String BingMapsToken = "BingMapsToken by Bing Maps dev center ";
在MainPage.xmal.cs代碼文件的頂部手動添加命名空間聲明。
using Windows.UI.Xaml.Controls.Maps;
using Windows.Devices.Geolocation;
在 MapControl 類的 MapControlLoaded方法中添加以下的代碼,顯示3D地圖並設定地圖中心:
File: MainPage.xaml.cs
public BasicGeoposition seattleLocation = new BasicGeoposition()
{
//Geopoint for Seattle
Latitude = 47.604,
Longitude = -122.329
};
public BasicGeoposition spaceNeedlePosition = new BasicGeoposition()
{
//Geopoint for Seattle
Latitude = 47.6204,
Longitude = -122.3491
};
private async void MapControlLoaded(object sender, RoutedEventArgs e)
{
myMapControl.Center = new Geopoint(seattleLocation);
myMapControl.ZoomLevel = 12;
if (myMapControl.Is3DSupported)
{
this.myMapControl.Style = MapStyle.Aerial3DWithRoads;
Geopoint spaceNeedlePoint = new Geopoint(seattleLocation);
MapScene spaceNeedleScene = MapScene.CreateFromLocationAndRadius(spaceNeedlePoint,
400, /* show this many meters around */
135, /* looking at it to the south east*/
60 /* degrees pitch */);
await myMapControl.TrySetSceneAsync(spaceNeedleScene);
}
else
{
//string status = "3D views are not supported on this device.";
this.myMapControl.Style = MapStyle.Aerial;
}
}
可以使用MapControl 的 Is3DSupported 方法判斷設備是否支持3D地圖顯示,代碼
this.myMapControl.Style = MapStyle.Aerial3DWithRoads;
實現了地圖的切換至3D模式。調用MapControl.TrySetSceneAsync 方法切換地圖場景。
其中 使用BasicGeoposition 類實例化兩個演示地點 seattleLocation 和 spaceNeedlePosition。
可經過將圖釘、圖像和形狀添加到 MapElements 集合,在 MapControl 上顯示集合中的圖釘或者圖像。
提示 在 XAML 標記中,沒法以聲明方式綁定到 MapElements 集合。
如下是未對 Title 屬性指定任何值的MapIcon默認圖像。
下面的示例顯示了 Seattle 的地圖並添加了自定義圖像和標題的 MapIcon,來指示 Space Needle 的位置。您能夠更具您應用的邏輯在須要的時候添加圖釘,好比在OnNavigatedTo 方法中設定。本例中在MainPage.xmal.cs代碼文件中的 MapControlLoaded 方法中添加圖釘。
File: MainPage.xaml.cs
MapIcon seattleMapIcon = new MapIcon();
seattleMapIcon.Location = new Geopoint(seattleLocation);
seattleMapIcon.NormalizedAnchorPoint = new Point(0.5, 1.0);
seattleMapIcon.Title = "Parking here";
seattleMapIcon.Image = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/mappin.png"));
myMapControl.MapElements.Add(seattleMapIcon);
在Windows 10 應用設計的典型特徵就是 SplitView 和 Hamburger,本文固然不會漏過此新特性。
在 MainPage.xaml 中添加以下代碼:
<SplitView x:Name="Splitter" IsPaneOpen="False" DisplayMode="CompactInline">
<SplitView.Pane>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="70"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListView x:Name="NavLinksList" Grid.Row="1" Margin="0,12,0,0" SelectionMode="None" VerticalAlignment="Stretch"
IsItemClickEnabled="True" ItemClick="NavLinksList_ItemClick"
ItemsSource="{x:Bind NavLinks}" ItemTemplate="{StaticResource NavLinkItemTemplate}"/>
<StackPanel Grid.Row="2" Orientation="Horizontal" Margin="14,24,0,24" >
<SymbolIcon Symbol="Setting" />
<TextBlock Text="Settings" Margin="24,0,0,0" VerticalAlignment="Center"/>
</StackPanel>
</Grid>
</SplitView.Pane>
</SplitView>
<FontIcon HorizontalAlignment="Left"
Margin="14,40,0,0"
VerticalAlignment="Top"
x:Name="Hamburger"
FontFamily="Segoe MDL2 Assets"
Glyph=""
Foreground="Green"
PointerPressed="Button_Click" />
在 MainPage.xaml 中添加代碼設定ListView 的ItemTemplate:
<Page.Resources>
<DataTemplate x:Key="NavLinkItemTemplate" x:DataType="local:NavLink">
<StackPanel Orientation="Horizontal" Margin="2,0,0,0">
<SymbolIcon Symbol="{x:Bind Symbol}"/>
<TextBlock Text="{x:Bind Label}" Margin="24,0,0,0" VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
</Page.Resources>
ListView 的ItemsSource 以x:Bind方式綁定,綁定的數據源在 MainPage.xaml.cs 中設定:
private ObservableCollection<NavLink> _navLinks = new ObservableCollection<NavLink>()
{
new NavLink() { Label = "Map", Symbol = Windows.UI.Xaml.Controls.Symbol.Map },
new NavLink() { Label = "MapDrive", Symbol = Windows.UI.Xaml.Controls.Symbol.MapDrive },
new NavLink() { Label = "MapPin", Symbol = Windows.UI.Xaml.Controls.Symbol.MapPin },
new NavLink() { Label = "Camera", Symbol = Windows.UI.Xaml.Controls.Symbol.Camera },
};
public ObservableCollection<NavLink> NavLinks
{
get { return _navLinks; }
}
咱們在ListView 中的ItemClick 事件可響應用戶的交互。在MainPage.xaml.cs中實現 NavLinksList_ItemClick 方法,經過判斷 ListView 中Item的 Lable 可知用戶究竟點擊了哪個Item,便可執行不一樣的業務邏輯。在本例中,咱們添加Lable爲"Map"的響應切換地圖顯示模式,其代碼以下:
private void NavLinksList_ItemClick(object sender, ItemClickEventArgs e)
{
String label = (e.ClickedItem as NavLink).Label;
switch (label)
{
case "Map":
if (myMapControl.Is3DSupported)
{
if ( this.myMapControl.Style == MapStyle.Aerial3DWithRoads)
{
this.myMapControl.Style = MapStyle.Road;
}
else
{
this.myMapControl.Style = MapStyle.Aerial3DWithRoads;
}
MapIcon seattleMapIcon = new MapIcon();
seattleMapIcon.Location = new Geopoint(seattleLocation);
seattleMapIcon.NormalizedAnchorPoint = new Point(0.5, 1.0);
seattleMapIcon.Title = "Parking here";
seattleMapIcon.Image = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/mappin.png"));
myMapControl.MapElements.Add(seattleMapIcon);
}
break;
default:
break;
}
}
在前面的代碼中咱們將FontIcon的x:Name 屬性設定爲Hamburger,如今 MainPage.xaml.cs 中添加PointerPressed 事件響應Button_Click 即實現了Windows 10 的Hamburger。
private void Button_Click(object sender, RoutedEventArgs e)
{
Splitter.IsPaneOpen = (Splitter.IsPaneOpen == true) ? false : true;
//StatusBorder.Visibility = Visibility.Collapsed;
}
代碼運行效果以下:
若是您的設備支持多點手勢觸控,則旋轉地圖,效果超酷。旋轉後可清晰看到圖釘的文字"Parking here"。
點擊 Hamburger 的 "Map"按鈕切換地圖顯示模式,以下圖所示。
使用 Visual Studio 2015 開發 Windows 10 應用時,您會看到下圖的提示,提醒您激活開發者模式。
那麼如何激活開發者模呢?
若是您的Windows 10已經升級至 Pro Insider Preview Evaluation Copy. Build 10130 以上,或者您看此文時Windows 10 正式版已經發布,那麼在 Settings 選擇 Update & security > For developers ,選擇 Developer Mode 激活開發者模式。
Windows 10 Phones
在 Settings 選擇 Update & security,而後選擇 For developers 。
Windows 10 desktop
Use gpedit to enable your device
Use regedit to enable your device
Use PowerShell to enable your device
做者:雪松
Microsoft MVP -- Windows Platform Development,
Hortonworks Certified Apache Hadoop 2.0 Developer