入力された住所の位置をBing Mapsに表示する

2011年12月16日(金)
PROJECT KySS

次に、MainPage.xamlを展開して表示される、MainPage.xaml.vbをダブルクリックしてリスト3のコードを記述します。

ロジックコードを記述する

リスト3 (MainPage.xaml.vb)

Option Strict On
Imports System.Xml.Linq

Partial Public Class MainPage
  Inherits PhoneApplicationPage

  ' コンストラクター
  Public Sub New()
    InitializeComponent()
  End Sub
定数変数AppIDを宣言し、値に「Bing Maps Account Centerより取得したApplicationID」を指定します。
  Const AppID  As String= " Bing Maps Account Centerより取得したApplicationID "

XML要素を表すXElementクラス型のメンバ変数xmldocを宣言します。
  Dim xmldoc As XElement

  Dim prefName As String = String.Empty

ページが読み込まれた時の処理

XElement.LoadメソッドでXML文書ファイル(pref.xml)を読み込みます。文字列型の新しいリストである、prefListオブジェクトを作成します。
Descendants メソッドで、子孫要素であるすべての <都道府県> 要素のコレクションに対して、各要素を変数 result に格納しながら、リストであるprefListオブジェクトにAddメソッドで、<都道府県>要素の値を追加していきます。ListBoxである、prefListBoxのItemsSourceプロパティにprefListオブジェクトを指定します。ListBox内に都道府県の一覧が表示されます。
    Private Sub MainPage_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
    xmldoc = XElement.Load("pref.xml")
    Dim prefList As New List(Of String)
 
    For Each result In From c In xmldoc.Descendants("都道府県") Select c
      prefList.Add(result.Value)
    Next
    prefListBox.ItemsSource = prefList
  End Sub

[実行]ボタンがタップされた時の処理

API へのリクエストは、adminDistrict、locality、addressLine、keyなどの条件を下記のような URL で指定します(REST)。
adminDistrictには「都道府県」、localityには「市区町村」、addressLineには「番地」、keyには「Bing Maps Account Centerより取得したApplicationID」を指定します。最後のoには結果レスポンスされるデータの形式を指定します。ここではxmlを指定しています。JSONを指定することもできます。「市区町村」、「番地」に指定する値は、UrlEncodeで文字列をエンコードしています。「都道府県」はListBoxから選択された時点でエンコードしています。
Dim myUri As String = String.Format("http://dev.virtualearth.net/REST/v1/Locations?countryRegion=JP&adminDistrict={0}&locality={1}&addressLine={2}&key={3}&c=ja-jp&o=xml", prefName, HttpUtility.UrlEncode(cityTextBox.Text), HttpUtility.UrlEncode(numberTextBox.Text), AppID)
例えば、京都府京都市伏見区桃山町丹後9番地と入力して返されるXMLは、図8のようなXMLです。

図8:返された結果XML(クリックで拡大)
新しいWebClientのインスタンスmyWebClientオブジェクトを生成します。DownloadStringAsyncメソッドで、Uri として指定したリソースをダウンロードします。
AddHandler ステートメントでダウンロードが完了した DownloadStringCompleted イベントに、イベント ハンドラーを追加します。イベント ハンドラー内では、ダウンロードされた文字列としての結果 XML(resultArgs.Result) を変数readXmldocに格納します。図8を見るとわかりますが、いろいろな名前空間が付属しています。このままではXMLの内容を取り出すことができません。そこで、Replace関数を使って、不要な名前空間を空白にしてしまいます。不要な名前空間の無くなったreadXmldocをXElement.Parseメソッドで文字列として読み込みます。
<Location>要素の子要素<Name>の値を変数addressNameに格納します。
<Point>要素の子要素<Latitude>(緯度)の値をmyLatitude変数に格納します。
<Point>要素の子要素<Longitude>(経度)の値をmyLongitudeに格納します。
これらの値を引数にして、MapPage.xamlに遷移します。
  Private Sub Button1_Click(sender As Object, e As System.Windows.RoutedEventArgs) Handles Button1.Click
    Dim myUri As String = String.Format("http://dev.virtualearth.net/REST/v1/Locations?countryRegion=JP&adminDistrict={0}&locality={1}&addressLine={2}&key={3}&c=ja-jp&o=xml", prefName, HttpUtility.UrlEncode(cityTextBox.Text), HttpUtility.UrlEncode(numberTextBox.Text), AppID)
    Dim myWebClient As New WebClient
    myWebClient.DownloadStringAsync(New Uri(myUri, UriKind.Absolute))
 
    AddHandler myWebClient.DownloadStringCompleted, Sub(resultSender As Object, resultArgs As DownloadStringCompletedEventArgs)
                                                    Dim readXmldoc As String = resultArgs.Result
        readXmldoc = readXmldoc.Replace("xmlns:xsi=" & ChrW(34) & "http://www.w3.org/2001/XMLSchema-instance" & ChrW(34) & " xmlns:xsd=" & ChrW(34) & "http://www.w3.org/2001/XMLSchema" & ChrW(34) & " xmlns=" & ChrW(34) & "http://schemas.microsoft.com/search/local/ws/rest/v1" & ChrW(34), "")
        Dim doc As XElement = XElement.Parse(readXmldoc)
        Dim addressName As String = HttpUtility.UrlEncode(doc.Descendants("Location").Elements("Name").Value)
        Dim myLatitude As String = HttpUtility.UrlEncode(doc.Descendants("Point").Elements("Latitude").Value)
        Dim myLongitude As String = HttpUtility.UrlEncode(doc.Descendants("Point").Elements("Longitude").Value)
        NavigationService.Navigate(New Uri(String.Format("/MapPage.xaml?latitude={0}&longitude={1}&name={2}", myLatitude, myLongitude, addressName), UriKind.Relative))
          End Sub
  End Sub

ListBox(prefListBox)から任意の都道府県名が選択された時の処理

ListBoxから項目が選択された時は、選択された都道府県名をエンコードして、メンバ変数prefNameに格納します。都道府県名が選択されていない時は、メッセージを表示します。
  Private Sub prefListBox_SelectionChanged(sender As Object, e As System.Windows.Controls.SelectionChangedEventArgs) Handles prefListBox.SelectionChanged
    If prefListBox.SelectedIndex >= 0 Then
      prefName = HttpUtility.UrlEncode(prefListBox.SelectedItem.ToString)
    Else
      MessageBox.Show("都道府県を選択してください。")
    End If
  End Sub
End Class

MapPage.xamlを展開して表示される、MapPage.xaml.vbをダブルクリックしてリスト4のコードを記述します。

ロジックコードを記述する

リスト4 (MapPage.xaml.vb)

Option Strict On
位置情報に関するクラスの含まれる、System.Device.Location名前空間をインポートします。
Imports System.Device.Location
Windows Phoneのための、Bing Maps Silverlight Controlのパブリッククラスを含む、Microsoft.Phone.Controls.Maps名前空間をインポートします。
Imports Microsoft.Phone.Controls.Maps
Partial Public Class MapPage
  Inherits PhoneApplicationPage

  Public Sub New()
    InitializeComponent()
  End Sub

ページがアクティブになった時の処理

Mainpage.xamlから渡された文字データを受け取ります。文字データはNavigationContextのQueryStringにDictionary として提供されます。各変数に受け取ったデータを格納します。
地図を移動させるには、MapのCenterプロパティに、GeoCoordinateメソッドにダブル型の緯度と経度(引数で渡した値)を指定します。緯度は、myParam("latitude")で取得し、経度はmyParam("longitude")で取得します。これらの値を格納した、myLatitude、myLongitudeの値をDouble型に変換して指定します。
PushPinクラスの新しいインスタンスmyPinオブジェクトを生成します。Locationプロパティに、GeoCoordinateメソッドを使って緯度と経度を指定します。ContentプロパティにはmyParam(“name”)の値を格納した、myAddress変数を指定します。ピン上に住所が表示されます。緯度と経度とContentの指定されたmyPinオブジェクトをAddメソッドでMapに追加します。これで指定した位置にピンが立ちます。

  Protected Overrides Sub OnNavigatedTo(e As System.Windows.Navigation.NavigationEventArgs)
    Dim myParam As IDictionary(Of String, String) = NavigationContext.QueryString
    Dim myLatitude = myParam("latitude")
    Dim myLongitude = myParam("longitude")
    Dim myAddress = myParam("name")
 
    Map1.Center = New GeoCoordinate(CDbl(myLatitude), CDbl(myLongitude))
    Dim myPin As New Pushpin
    myPin.Location = New GeoCoordinate(Double.Parse(myLatitude), Double.Parse(myLongitude))
    myPin.Content = myAddress
 
    Map1.Children.Add(myPin)
 
    MyBase.OnNavigatedTo(e)
  End Sub

ページが読み込まれた時の処理

ZoomLevelプロパティに10を指定します。ZoomLevelプロパティを指定しないと地図が表示されませんので注意してください。
  Private Sub MapPage_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
    Map1.ZoomLevel = 10
  End Sub

[航空写真]がタップされた時の処理

ボタンの文字で条件分岐を行います。
ボタンの文字が「航空写真」の時タップされれば、地図は航空写真モードで表示されます。ボタンの文字は「道路表示」に変わります。
ボタンの文字が「道路表示」の時タップされれば、地図は道路表示モードで表示されます。ボタンの文字は「航空写真」に変わります。
  Private Sub Button1_Click(sender As Object, e As System.Windows.RoutedEventArgs) Handles Button1.Click
    Select Case Button1.Content.ToString
      Case "航空写真"
        Map1.Mode = New AerialMode
        Button1.Content = "道路表示"
      Case "道路表示"
        Map1.Mode = New RoadMode
        Button1.Content = "航空写真"
    End Select
  End Sub
End Class
  • 「入力された住所の位置をBing Mapsに表示する」サンプルプログラム

四国のSOHO。薬師寺国安(VBプログラマ)と、薬師寺聖(デザイナ、エンジニア)によるコラボレーション・ユニット。1997年6月、Dynamic HTMLとDirectAnimationの普及を目的として結成。共同開発やユニット名義での執筆活動を行う。XMLおよび.NETに関する著書や連載多数。最新刊は「Silverlight実践プログラミング」両名とも、Microsoft MVP for Development Platforms - Client App Dev (Oct 2003-Sep 2012)。http://www.PROJECTKySS.NET/

連載バックナンバー

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

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

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

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