地震の震源地を表示する

2012年1月10日(火)
PROJECT KySS

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

Mapのズームを6に設定します。
API へのリクエストは、下記のような URL で指定します。(REST)
Dim myUri As Uri = New Uri("http://nmz.mogken.com/api?c=10&f=xml", UriKind.Absolute)
  cには表示する最大データ件数、ここでは10個を指定しています。fには返されるデータ形式を指定します。ここではxmlを指定しています。jsonを指定することも可能です。このURLで返されるXMLのデータ構造は図4のようになります。

図4:返されるXMLの構造(クリックで拡大)
新しいWebClientのインスタンスmyWebClientオブジェクトを生成します。DownloadStringAsyncメソッドで、Uri として指定したリソースをダウンロードします。
各文字列変数を初期化しておきます。変数myDateに-で連結した現在の、年、月、日の値を格納します。月と日は01、02のような型にするため、Tostring(“00”)と指定しています。
AddHandler ステートメントでダウンロードが完了した DownloadStringCompleted イベントに、イベント ハンドラを追加します。イベント ハンドラ内では、ダウンロードされた文字列としての結果 XML(resultArgs.Result) をXElement.Parseメソッドで文字列として読み込みます。
図4の構造の、XMLの内容テキストを取得していきます。
Descendants メソッドで、子孫要素であるすべての <item> 要素のコレクションに対して、各要素を変数 result に格納しながら、各変数に<epicenter_location_name>要素の値(震源地)、<detection_date>要素の値(発生日時)、<epicenter_coor_lat>要素の値(震源地の緯度)、<epicenter_coor_long>要素の値(震源地の経度)、< magnitude>要素の値(マグニチュード)、<intensity>要素の値(震度)を格納していきます。
地図を移動させるには、MapのCenterプロパティに、GeoCoordinateメソッドにダブル型の緯度と経度を指定します。緯度は、変数myLatitudeの値、経度はmyLongitudeの値をダブル型に変換して指定しています。
PushPinクラスの新しいインスタンスmyPinオブジェクトを生成します。
発生日時がmyDate変数の値、すなはち、本日であった場合は、ピンの背景色を赤色に指定します。それ以外は黄色になります。ピンの文字色は青色を指定します。ピンのLocationプロパティに、GeoCoordinateメソッドを使って緯度と経度を指定します。Contentプロパティには地震発生日時を指定します。Tagプロパティに1ずつ増加する変数noの値を文字列に変換して指定します。この値は図4の選択された<item>要素のインデックス番号として使用します。緯度と経度とContentの指定されたmyPinオブジェクトをAddメソッドでMapに追加します。これで指定した位置にピンが立ちます。
AddHandlerステートメントで、ピンがホールドされた時に実行される、myPin_Holdイベントハンドラを追加します。
新しいMeuItemクラスのインスタンスmyMenuItemオブジェクトを作成します。Headerプロパティに「地震の詳細を表示」と指定します。menuItem型として宣言しておいたメンバ変数menuItemListオブジェクトにAddメソッドでmyMenuItemオブジェクトを追加します。ContextMenuのItemsSourceプロパティに、menuItemListオブジェクトを指定します。ContetMenuに表示されるMenuItemをタップした時にmyMenuItem_Clickイベントハンドラを実行します。
  Protected Overrides Sub OnNavigatedTo(e As System.Windows.Navigation.NavigationEventArgs)
    Map1.ZoomLevel = 6
    Dim myUri As Uri = New Uri("http://nmz.mogken.com/api?c=10&f=xml", UriKind.Absolute)
 
    Dim myWebClient As New WebClient
    myWebClient.DownloadStringAsync(myUri)
 
    Dim detectionDate As String = String.Empty
    Dim myLocation As String = String.Empty
    Dim myLatitude As String = String.Empty
    Dim myLongitude As String = String.Empty
    Dim myMagnitude As String = String.Empty
    Dim myIntensity As String = String.Empty
 
    Dim nowYear As Integer = Date.Now.Year
    Dim nowMonth As Integer = Date.Now.Month
    Dim nowDay As Integer = Date.Now.Day
 
    Dim myDate As String = nowYear.ToString & "-" & nowMonth.ToString("00") & "-" & nowDay.ToString("00")
 
    no = 0
    AddHandler myWebClient.DownloadStringCompleted, Sub(resultSender As Object, resultArgs As DownloadStringCompletedEventArgs)
              xmldoc = XElement.Parse(resultArgs.Result)
              For Each result In From c In xmldoc.Elements("item") Select c
                  myLocation = result.Element("epicenter_location_name").Value
                  detectionDate = result.Element("detection_date").Value
                  myLatitude = result.Element("epicenter_coor_lat").Value
                  myLongitude = result.Element("epicenter_coor_long").Value
                  myMagnitude = result.Element("magnitude").Value
                  myIntensity = result.Element("intensity").Value
                  Map1.Center = New GeoCoordinate(Double.Parse(myLatitude), Double.Parse(myLongitude))
                  Dim myPin As New Pushpin
                  If detectionDate.Contains(myDate) = True Then
                      myPin.Background = New SolidColorBrush(Colors.Red)
                  Else
                      myPin.Background = New SolidColorBrush(Colors.Yellow)
                  End If
                    myPin.Foreground = New SolidColorBrush(Colors.Blue)
                    myPin.Location = New GeoCoordinate(Double.Parse(myLatitude), Double.Parse(myLongitude))
                    myPin.Content = "地震発生日時=" & detectionDate
                    myPin.Tag = no.ToString
                    no = no + 1
                    Map1.Children.Add(myPin)
                    
                    AddHandler myPin.Hold, AddressOf myPin_Hold
              Next
              Dim myMenuItem As New MenuItem
              myMenuItem.Header = "地震の詳細を表示"
              menuItemList.Add(myMenuItem)
                ContextMenu1.ItemsSource = menuItemList
                AddHandler myMenuItem.Click, AddressOf myMenuItem_Click
                    End Sub
    MyBase.OnNavigatedTo(e)
  End Sub

ピンがホールドされた時の処理

ContextMenuを表示します。
PushPinのTagプロパティに指定した値を、数値に変換して変数indexに格納します。
  Private Sub myPin_Hold(sender As Object, e As System.Windows.Input.GestureEventArgs)
    ContextMenu1.IsOpen = True
    index = Integer.Parse(DirectCast(sender, Pushpin).Tag.ToString)
  End Sub

ピンをホールドした時に表示されるメニューをタップした時の処理

MenuItemのHeaderプロパティの値で条件分岐を行います。
Headerの値が「地震の詳細を表示」であった場合は、選択されたピンのindexに該当する<item>要素の、< epicenter_location_name>(震源地)の値、<detection_date>(発生日時)の値、<intensity>(震度)の値、<magnitude>(マグニチュード)の値、を変数に格納し、この変数を引数にDetailsPage.xamlに遷移します。
  Private Sub myMenuItem_Click(sender As Object, e As EventArgs)
    Dim selectHeader = DirectCast(sender, MenuItem).Header
    Select Case selectHeader.ToString
      Case "地震の詳細を表示"
        Dim location As String = xmldoc.Elements("item")(index).Element("epicenter_location_name").Value '震源地
        Dim quakeDate As String = xmldoc.Elements("item")(index).Element("detection_date").Value '発生日時
        Dim intnsity As String = xmldoc.Elements("item")(index).Element("intensity").Value '震度
        Dim magnitude As String = xmldoc.Elements("item")(index).Element("magnitude").Value 'マグニチュード
        NavigationService.Navigate(New Uri(String.Format("/DetailsPage.xaml?myDate={0}&myPlace={1}&myMagnitude={2}&myIntnisity={3}", quakeDate, location, magnitude, intnsity), UriKind.Relative))
      Case Else
        Exit Sub
    End Select
  End Sub

End Class

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

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

リスト4 (DetailsPage.xaml.vb)

Option Strict On

Partial Public Class DetailsPage
  Inherits PhoneApplicationPage
 
  Public Sub New()
    InitializeComponent()
  End Sub

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

Mainpage.xamlから渡された文字データを受け取ります。文字データはNavigationContextのQueryStringにDictionary として提供されます。
各TextBoxに、受け取った文字データを表示します。
  Protected Overrides Sub OnNavigatedTo(e As System.Windows.Navigation.NavigationEventArgs)
    Dim myParam As IDictionary(Of String, String) = NavigationContext.QueryString
    PageTitle.Text = myParam("myPlace")
    dateTextBlock.Text = myParam("myDate")
    locationTextBlock.Text = myParam("myPlace")
    magnitudeTextBlock.Text = myParam("myMagnitude")
    intensityTextBlock.Text = myParam("myIntnisity")
    MyBase.OnNavigatedTo(e)
  End Sub
End Class
  • 「地震の震源地を表示する」サンプルプログラム

四国の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メルマガ会員のサービス内容を見る

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