キャラクターが声で天気予報を教えてくれるアプリを作る

2014年2月26日(水)
薬師寺 国安

次に、ソリューション・エクスプローラー内のBingMapsPage.xamlを展開して表示される、BingMapsPage.xaml.vbをダブルクリックしてリスト5のコードを記述します。

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

リスト5 (BingMapsPage.xaml.vb)

01Imports System.Net.Http
02 
03‘ Bing Mapsに関するクラスの含まれるBing.Maps名前空間を読み込みます。
04 
05Imports Bing.Maps
06 
07Imports Windows.UI
08Imports Windows.UI.Popups
09 
10‘ TenkiInfoクラス内に文字列型の「日付」、「天気」、「画像」、「最高気温」、「最低気温」プロパティを定義しておきます。
11 
12Public Class TenkiInfo
13  Public Property 日付 As String
14  Public Property 天気 As String
15  Public Property 画像 As String
16  Public Property 最高気温 As String
17  Public Property 最低気温 As String
18End Class
19Public NotInheritable Class BingMapsPage
20  Inherits Page
21 
22‘ 選択した都道府県のURIを格納するメンバー変数myUriを宣言します。
23 
24  Private myUri As String
25 
26‘ 「地域」のデータを格納するメンバー変数areaDataを宣言します。
27 
28  Private areaData As String
29 
30‘ 緯度のデータを格納するmyLatitudeメンバー変数を宣言します。
31 
32  Private myLatitude As String
33 
34‘ 経度のデータを格納するメンバー変数myLongitudeを宣言します。
35 
36  Private myLongitude As String
37 
38  Private no As Integer = 0
39 
40‘ HttpClientクラス型のメンバー変数myHttpClientを宣言します。
41 
42  Private myHttpClient As HttpClient
43 
44  Private resultXml As String
45 
46‘ XML要素を表すXElementクラス型のメンバー変数xmldocを宣言します。
47 
48  Private xmldoc As XElement
49 
50‘ 指定したコレクションに対する単純な反復処理をサポートする列挙子である、
51‘ インターフェイス型のメンバー変数queryを宣言します。
52 
53  Private query As IEnumerable(Of System.Xml.Linq.XElement)
54 
55‘ 新しいPushPinクラスのインスタンスである、myPinメンバー変数を宣言します。
56 
57  Private myPin As New Pushpin
58  Private myInfoCount As Integer
59 
60‘ TextBlockクラス型のmyDateTextBlockとmyTenkiTextBlockメンバー変数を宣言します。
61 
62  Private myDateTextBlock As TextBlock
63  Private myTenkiTextBlock As TextBlock
64 
65‘ Imageクラス型のメンバー変数myImageを宣言します。
66  
67  Private myImage As Image
68 
69‘ TextBlockクラス型のメンバー変数、maxTextBlcokとminTextBlockを宣言します。
70‘ 最高気温の値と最低気温の値が格納されます。
71 
72  Private maxTextBlock As TextBlock
73  Private minTextBlock As TextBlock
74 
75‘ StackPaneクラス型のメンバー変数myTenkiStackPanelメンバー変数を宣言します。
76 
77  Private myTenkiStackPanel As StackPanel
78 
79‘ Buttonクラス型のメンバー変数nextButtonとprevButtonメンバー変数を宣言します。
80 
81  Private nextButton As Button
82  Private prevButton As Button
83 
84‘ キャラクターが読み上げる内容を格納するメンバー変数readingTenkiを宣言します。
85 
86  Private readingTenki As String

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

MainPageから送られてきた値をe.Parameterで受け取ります。Object型であるため、DirectCastで文字列にキャストします。

送られてきたデータは都道府県のURIと地域名がカンマで区切られて送られてきていますので、Split関数で分解し、配列変数myDataに格納します。

メンバー変数myUriには、配列変数myData(0)の値を格納します。都道府県のURIが格納されます。

メンバー変数areaDataには、配列変数myData(1)の値を格納します。「地域名」が格納されます。

新しいHttpClientのインスタンスmyHttpClientオブジェクトを作成し、GetStringAsyncメソッドで、指定したURIにGET要求を送信し、非同期操作で応答本体を文字列として受け取り、メンバー変数resultXmlに格納します。

XElement.ParseメソッドでresultXmlの値を文字列として読み込みます。

要素の属性”id”がメンバー変数areaDataと同じである要素を選択するクエリを定義します。
PushPinの背景色を「Crimson」に指定し、枠線を「3」に枠線の色を「Navy」に指定しておきます。

メンバー変数myLatitudeに要素の子要素の値を格納します。

メンバー変数myLongitudeには要素の子要素の値を格納します。

これらXMLの構造については図7を参照してください。

myLatitudeやmyLongitudeの値が空であった場合は、警告メッセージを発して処理を抜けます。そうでない場合は、新しいLocationのインスタンスを作成し、myLatutudeとmyLonditudeで初期化し、変数myLocationで参照します。

MapLayer.SetPosition(myPin, myLocation)

と指定すると、指定した緯度、経度の位置にピンが立ちます。

myMapにmyPinオブジェクトを追加します。

SetViewメソッドでmyLocationの位置にズームインします。

TenkiInfoクラスの新しいリストであるmyTenkiInfoオブジェクトを作成します。

TenkiInfoクラスの「日付」プロパティに要素内にある要素の属性”date”の値を指定します。
「天気」プロパティには要素の値を、「画像」プロパティには要素の値を、「最高気温」プロパティには、要素の子要素要素でインデックスが0の値を指定します。
「最低気温」プロパティには要素の子要素要素でインデックスが1の値を指定し、AddメソッドでmyTenkiInfoオブジェクトに追加します。

GridView1のItemsSourceプロパティにmyTenkiInfoオブジェクトを指定します。これでマウスの右クリックをすると、アプリケーションバー内に天気予報の一覧が表示されます。

ピンの位置に今日の天気予報を表示するDataShowタスクを実行します。

01Protected Overrides Async Sub OnNavigatedTo(e As Navigation.NavigationEventArgs)
02 
03  Dim getMapsData As String = DirectCast(e.Parameter, String)
04  Dim myData() As String = getMapsData.Split(CChar(","))
05  myUri = myData(0)
06  areaData = myData(1)
07  myHttpClient = New HttpClient
08  resultXml = Await myHttpClient.GetStringAsync(myUri)
09  xmldoc = XElement.Parse(resultXml)
10  query = From c In xmldoc.Descendants("area") Where c.Attribute("id").Value.Equals(areaData) Select c
11 
12  myPin.Background = New SolidColorBrush(Colors.Crimson)
13  myPin.BorderThickness = New Thickness(3)
14  myPin.BorderBrush = New SolidColorBrush(Colors.Navy)
15 
16  myLatitude = query.Descendants("geo").Elements("lat").Value
17  myLongitude = query.Descendants("geo").Elements("long").Value
18  If myLatitude = String.Empty AndAlso myLongitude = String.Empty Then
19    Dim message = New MessageDialog("緯度、経度が設定されていませんので、表示できません。")
20    Await message.ShowAsync
21    Exit Sub
22  Else
23    Dim myLocation = New Location(CDbl(myLatitude), CDbl(myLongitude))
24    MapLayer.SetPosition(myPin, myLocation)
25    myMap.Children.Add(myPin)
26    myMap.SetView(myLocation, 10)
27 
28  End If
29 
30    Dim myTenkiInfo As New List(Of TenkiInfo)
31 
32    For Each result In query
33      For Each result2 In result.Descendants("info")
34        With myTenkiInfo
35.Add(New TenkiInfo With {.日付 = CStr(result2.Attributes("date").First), _
36                         .天気 = result2.Elements("weather").Value, _
37                         .画像 = result2.Elements("img").Value, _
38                         .最高気温 = result2.Elements("temperature").Elements("range")(0).Value & "℃", _
39                         .最低気温 = result2.Elements("temperature").Elements("range")(1).Value})
40        End With
41      Next
42    Next
43    GridView1.ItemsSource = myTenkiInfo
44    Await DataShow()
45  End Sub
  • キャラクター音声天気予報アプリのサンプル

    『Windows 8.1+Visual Studio 2013によるWindows ストア・アプリ開発実例集』 第8回のサンプルプログラムです。
薬師寺国安事務所

薬師寺国安事務所代表。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メルマガ会員のサービス内容を見る

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