MapControlを使ってみよう!

2015年11月18日(水)
薬師寺 国安

前回は、GridViewコントロールを使って、画面サイズに合わせて画像の表示方法を変化させる方法を解説しました。最終回の今回は、「MapControl」を使用して「Google Map」のようなユニバーサルアプリの開発方法を見ていきます。

MapControlとは

MapControlは地図を表示するコントロールで、いろいろな形式で表示させることができます。詳細については、下記のURLを参照してください。

MapControl class
https://msdn.microsoft.com/library/windows/apps/windows.ui.xaml.controls.maps.mapcontrol.aspx

プロジェクトの作成

Visual Studio Community 2015を起動し、新しいプロジェクトを作成します。詳細な手順は、第2回の「プロジェクトの作成」の項を参照してください。なお、今回の「プロジェクト名」は「UniversalApp6」と指定します。

[OK]ボタンをクリックすると、「UniversalApp6」のプロジェクトが起動します。ソリューションエクスプローラー内のMainPage.xamlをダブルクリックすると、デザイン画面とXAMLコードの記述された画面が表示されます。このデザイン画面にコントロールを配置していきます。

新しいフォルダーの作成と画像の追加

コントロールを配置する前に、ソリューションエクスプローラー内に「Image」というフォルダーを作成します。

次に、作成した「Image」フォルダーを選択した状態でマウスを右クリックして、メニューから「追加」→「既存の項目」と選択してMapControlの任意の位置に表示するピンの画像(mappin.png)を追加します(図1)。新しいフォルダーの作成と画像を追加する詳細な手順は、第2回の「新しいフォルダーの作成と画像の追加」の項を参照してください。なお、この画像はサンプルファイル内に含まれています。サンプルファイルはこちらからダウンロードできます(UniversalApp6.zip)。

コントロールの配置

続けて、コントロールを配置していきましょう。画面右のソリューションエクスプローラーから「MainPage.xaml」をダブルクリックすると、デザイン画面が表示されます。ここでデザイン画面が狭く表示されている場合は、デバイススケールの一覧から「23”Desktop(1920×1080)100%スケール」を選択してください。デザイン画面が広く表示されます(詳細は第2回の「コントロールの配置」の項を参照)。ツールボックスの「すべてのXAMLコントロール」からデザイン画面上にMapControlコントロールを1個配置します(図2)。MapControlを使用するには、実行時にMapServiceTokenを取得していないと図3のような警告が表示されます。

MapServiceTokenの取得

Bing Maps Dev Center」にアクセスし、Microsoft AccountでサインインしてBing Mapsのアカウントを作成します。表示される画面から「My Account」→「Create or view keys」をクリックします(図4)。

筆者の場合は既にkeyを作成していますが、初めてKeyを作成する場合は画面下部の「Click here to create a new key」のリンクをクリックしてください(図5)。

「My keys」の画面が表示されるので、任意の「Application name」を入力し、「Key type」と「Application type」はデフォルトのままで[Create]をクリックします(図6)。

これで、keyが作成され、図5のようにKeyの情報が表示されます。なお、「Key」はコピーして控えておいてください。MapControlを配置したデザイン画面は図7のようになります。MapControlのプロパティから、「レイアウト」にあるWidthを「1024」、Heightを「640」に指定しています。

ここまでの操作で、図7のMainPage.xamlはリスト1のようになっています。

リスト1: MainPage.xaml

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UniversalApp6"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:Maps="using:Windows.UI.Xaml.Controls.Maps"
    x:Class="UniversalApp6.MainPage"
    mc:Ignorable="d">
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Maps:MapControl x:Name="myMap" HorizontalAlignment="Left" Height="640" VerticalAlignment="Top" Width="1024"  Margin="247,0,0,0"/>(1)
    </Grid>
</Page>
  1. Nameが「myMap」というMapControlを配置

リスト1でmyMapのMapServiceTokenプロパティに、先ほど取得したkeyを指定します(リスト2)。

リスト2: MapServiceTokenにkeyを指定したMapControl

<Maps:MapControl x:Name="myMap" HorizontalAlignment="Left" Height="640" VerticalAlignment="Top" Width="1024"  Margin="247,0,0,0" MapServiceToken="Bing Map Dev Centerで取得したkeyを指定する" />

これで、「MapServiceTokenが設定されていません。」という警告は出なくなります。次に、ツールボックスからデザイン画面にButtonコントロールを3個配置します。上から順に「Name」を「Button1」~「Button3」と指定します。プロパティで書体や文字サイズを自由に設定してください。ただし、ContentプロパティだけButton1は「3D表示」、Button2は「ストリートビュー」、Button3は「道路表示」と指定しておきます。ここまでの操作で、デザイン画面は図8のようになります。

プログラムコードの記述

まずButton1を選択して、プロパティ上部の「名前」の右端にある「稲妻」アイコン(選択した要素のイベントハンドラー)をクリックします(図9)。

Button1の各種イベントが表示されるので、ここでイベントハンドラを作成します。一番上の「Click」の右側にある空欄をクリックすると「Button1_Click」と表示され(図10)、コードを記述する画面が表示されます。

同様に、Button2とButton3にもそれぞれのイベントハンドラを作成しておきます。また、「myMap」を選択して、同様にLoadedイベントにmyMap_Loadedイベントハンドラを作成しておきましょう(図11)。図12のようなコードが自動的に作成されます。

図12のコードエディタ内にリスト3のコードを記述します。

地図の目的地にピン(図1)を立て、ボタンのクリックで地図の表示方法を切り替えられるようにするため、リスト3のコードを記述します。

リスト3: MainPage.xaml.vb

‘ デバイスの現在の地理的な場所を取得したり、時間の経過によるデバイスの位置を追跡するための
‘ API を提供するWindows.Devices.Geolocation名前空間をインポートします。
Imports Windows.Devices.Geolocation
‘ シーケンシャル アクセス ストリームおよびランダム アクセス ストリームに対する読み取りと書き込みのサ
‘ ポートを提供するWindows.Storage.Streams名前空間をインポートします。
Imports Windows.Storage.Streams

‘ マップ コントロールのクラスを定義するWindows.UI.Xaml.Controls.Maps名前空間をインポート
‘ します。
Imports Windows.UI.Xaml.Controls.Maps

Public NotInheritable Class MainPage
    Inherits Page

‘ ●地図が読み込まれた時の処理
    Private Sub myMap_Loaded(sender As Object, e As RoutedEventArgs) Handles myMap.Loaded
        ‘ ファイルの入出力ストリームデータへのランダムアクセスを提供する、
‘ RandomAccessStreamReferenceクラス型の変数、mapIconStreamReference
‘ 変数を宣言します。
        Dim mapIconStreamReference As RandomAccessStreamReference

        ‘ RandomAccessStreamReference.CreateFromUriメソッドで、指定した URIにラン
‘ ダムアクセス ストリームを作成します。ここでは、UriにソリューションエクスプローラーのImage
‘ フォルダーにあるmappin.pngを指定しています。
        mapIconStreamReference = RandomAccessStreamReference.CreateFromUri(New Uri("ms-appx:///Image/mappin.png"))

        ‘ 地理的位置を表すBasicGeoPosition構造体の緯度(Latitude)と
‘ 経度(Longitude)を指定し、myMapのCenterプロパティに指定します。
‘ ここの経度と緯度は筆者の居住地の近辺を示しています。
‘ 指定した住所の緯度と経度を知りたい場合は、下記のURLで知ることができます。
‘ http://www.bing.com/maps/
        myMap.Center = New Geopoint(New BasicGeoposition With {.Latitude = 33.854034, .Longitude = 132.7798})

      ‘ 新しいMapIconクラスのインスタンスmyMapIconを生成します。
      ‘ MapIconクラスはMapControlのオプションのテキストとプッシュピンなどイメージを表示する
      ‘ クラスです。
        Dim myMapIcon As MapIcon = New MapIcon

      ‘ マップの中心を、MapControlのMapIconの地理的位置に設定します。
        myMapIcon.Location = myMap.Center

      ‘ MapIconのアンカーポイント(NormalizedAnchorPointプロパティ)を、xを0.5、yを
‘ 1.0の位置に指定します。
      ‘ NormalizedAnchorPointプロパティの既定値は、画像の左上隅を表す (0, 0) を値と
      ‘ して作成されたPointオブジェクトです。
        myMapIcon.NormalizedAnchorPoint = New Point(0.5, 1.0)

       ‘ Titleプロパティには「私の位置」と指定しておきます。
        myMapIcon.Title = "私の位置"

      ‘ MapIconオブジェクトのImageプロパティに、ソリューションエクスプローラー内のImage
      ‘ フォルダーにある画像を参照するmapIconStreamReferenceオブジェクトを指定します。
        myMapIcon.Image = mapIconStreamReference

        ‘ MapIconオブジェクトのZIndexに0を指定して、Mapより前面に表示するようにします。
        myMapIcon.ZIndex = 0

      ‘ MapElements.AddメソッドでMapにMapIconオブジェクトを追加します。これで指定し
‘ た経度と緯度の位置にmappin.pngが表示されます。
        myMap.MapElements.Add(myMapIcon)

        ‘ 地図の拡大率を17に指定します。
        myMap.ZoomLevel = 17
    End Sub

‘ ●「3D」表示ボタンがクリックされた時の処理
    Private Async Sub Button1_Click(sender As Object, e As RoutedEventArgs) Handles Button1.Click

     ‘ もし地図が「3D表示」をサポートしていた場合の処理です。
        If myMap.Is3DSupported Then
        ‘ 地図の表示スタイルを3D表示のMapStyle.Aerial3DWithRoadsに指定します。
            myMap.Style = MapStyle.Aerial3DWithRoads

        ‘ 地理的な位置を記述する基本的な情報を提供する、新しいBasicGeoPositionクラ
‘ スのインスタンス、dougoPositionオブジェトを作成します。
            Dim dougoPosition As BasicGeoposition = New BasicGeoposition

           ‘ dougoPositionオブジェクトの経度と緯度を指定します。この経度と緯度は筆者の住居
‘ の近く指しています。
            dougoPosition.Latitude = 33.854034
            dougoPosition.Longitude = 132.7798

           ‘ dougoPositionを引数にして、地理的な点を記述する新しいGeoPointクラスのインス
‘ タンス、dougoPointを作成します。
            Dim dougoPoint As Geopoint = New Geopoint(dougoPosition)

           ‘ 1つの地理的な位置、半径、方位、およびピッチに基づいてマップに表示するシーンを作
‘ 成するMapScene.CreateFromLocationAndRadiusメソッドに、dougoPointの
‘ 位置を指定し、半径に「400」、「方位」に「135」、ピッチに「60」を指定し、
‘ DougoSceneシーンを作成します。
            Dim dougoScene As MapScene = MapScene.CreateFromLocationAndRadius(dougoPoint, 400, 135, 60)

            ‘ TrySceneAsyncメソッドで、引数にdougoSceneを指定して、指定したシーンを使
‘ 用してMapControlに表示されるマップのシーンを表示します。
            ‘ これで道後周辺の地図が「3D表示」になります。
         Await myMap.TrySetSceneAsync(dougoScene)

‘ ●「ストリートビュー」ボタンがクリックされたときの処理です
    Private Async Sub Button2_Click(sender As Object, e As RoutedEventArgs) Handles Button2.Click
      ‘ 地図がストリートビューに対応している場合の処理です。
      ‘ 日本地図はストリートビューに対応していませんので、今回はNew Yorkの地図を表示させ
‘ ています。
        If myMap.IsStreetsideSupported Then
           ‘ 地理的な位置を記述する基本的な情報を提供する、新しいBasicGeoPositionクラ
‘ スのインスタンス、NewYorkPositionオブジェトを作成します。
            Dim NewYorkPosition As BasicGeoposition = New BasicGeoposition

            ‘ NewYorkPositionオブジェクトの経度と緯度を指定します。この経度と緯度は米国ニ
‘ ューヨークの経度と緯度です。
            NewYorkPosition.Latitude = 40.782001 '33.854034
            NewYorkPosition.Longitude = -73.831703 '132.7798

            ‘ NewYorkPositionを引数にして、地理的な点を記述する新しいGeoPointクラスの
‘ インスタンス、NewYorkPointを作成します。
            Dim NewYorkPoint As Geopoint = New Geopoint(NewYorkPosition)

        ‘ NewYorkPositionを引数にして、StreetsidePanorama.FindNearbyAsyncメソ
‘ ッドで、指定した地理的位置に近いStreetsidePanoramaを作成し、
‘ panoramaNewYork変数で参照します。
‘ StreetsidePanoramaクラスは、ストリート・レベルの観点からの地理的な場所のパノラ
‘ マビューを表わすクラスです。
            Dim panoramaNewYork As StreetsidePanorama = Await StreetsidePanorama.FindNearbyAsync(NewYorkPoint)

         ‘ 指定した経度緯度のStreetPanoramaが表示可能な場合は、指定されたパノラマ
   ‘ ビュー(panoramaNewYork)に基づいてStreetsideExperienceを作成します。
            If panoramaNewYork Is Nothing = False Then
                myMap.CustomExperience = New StreetsideExperience(panoramaNewYork)
            End If
        End If
    End Sub

‘ ●「道路表示」ボタンをクリックしたときの処理
    Private Sub Button3_Click(sender As Object, e As RoutedEventArgs) Handles Button3.Click
      ‘ 地図の表示スタイルを道路表示にします。
        myMap.Style = MapStyle.Road
    End Sub
End Class

それでは、記述したリスト3を実行してみましょう。「23”Desktop(920×1080)100%スケール」を選択し、ローカルコンピューターを選択します。実行結果は図13のようになります。マウスホイールで拡大・縮小が、ドラッグで地図を移動できます。最初は道路表示になっています。

図13で[3D表示]をクリックすると、松山市の道後近辺が3D表示に変わります(図14)。

次に、[ストリートビュー]ボタンをクリックすると、米国のニューヨーク近辺がストリートビューで表示されます(図15)。

ストリートビューから表示を切り替える場合は、図15の右隅上にある「×」アイコンをクリックしてストリートビューの表示を消し、ほかのボタンをクリックしてください。ただし、ストリートビューの「×」アイコンでストリートビューの表示を消しておかないと、ほかのボタンをクリックしても表示されないので注意してください。なお、原因は不明ですが、MapControlはWindows Phoneエミュレーターではエラーになります。

いかがでしょうか。皆さんの環境でも動作を確認できたでしょうか。なお、今回のサンプルファイルはこちらからダウンロードできます(UniversalApp6.zip)。

さて、今回で7回にわたって解説してきた本連載は終了です。MapControl以外のユニバーサルアプリの処理はXAMLの記述がほとんど定型化されているため、一度書き方さえ覚えてしまえば、あとはXAMLの中でプロパティの値を変化させるだけなので簡単ではないかと思います。本連載ではごく初歩的な記述法を紹介しましたが、基本となるところなのでしっかりと理解しておいていただきたいです。

また機会があれば、一歩進んだユニバーサルアプリの作成方法を紹介したいと思います。長い間のお付き合い、ありがとうございました。

薬師寺国安事務所

薬師寺国安事務所代表。Visual Basic プログラミングと、マイクロソフト系の技術をテーマとした、書籍や記事の執筆を行う。
1950年生まれ。事務系のサラリーマンだった40歳から趣味でプログラミングを始め、1996年より独学でActiveXに取り組む。1997年に薬師寺聖とコラボレーション・ユニット PROJECT KySS を結成。2003年よりフリーになり、PROJECT KySS の活動に本格的に参加、.NETやRIAに関する書籍や記事を多数執筆する傍ら、受託案件のプログラミングも手掛ける。Windows Phoneアプリ開発を経て、現在はWindows ストア アプリを多数公開中

Microsoft MVP for Development Platforms - Client App Dev (Oct 2003-Sep 2012)。Microsoft MVP for Development Platforms - Windows Phone Development(Oct 2012-Sep 2013)。Microsoft MVP for Development Platforms - Client Development(Oct 2013-Sep 2014)。Microsoft MVP for Development Platforms-Windows Platform Development (Oct 2014-Sep 2015)。

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています