Visual Basicでユニバーサルアプリに挑戦!
App1_Common(移植可能)プロジェクト内にMainPage.xamlを作成
ソリューションエクスプローラー内の「App1_Common(移植可能)」を選択し、マウスの右クリックメニューから[追加]ー[新しい項目]と選択します。表示される画面から[XAML]を選択し、「空白のページ」テンプレートを選択します。[名前]には「MainPage.xaml」と指定します(図11)。
[追加]ボタンをクリックします。すると、ソリューションエクスプローラー内の「App1_Common(移植可能)」プロジェクト内に「MainPage.xaml」と「MainPage.xaml.vb」が作成されます。この中にコードを記述します。
「Windows 8.1」か「Windows Phone 8.1」か、どちらをメインにコードを記述していくかは、図12で選択ができます。今回は、「Windows Phone 8.1」をメインにコードを書いていきます。「Windows 8.1」をメインにコードを記述すると、解像度の違いで、「Windows Phone 8.1」で実行した際、画面が極端に小さく表示されるからです。
先にも書いたように、デフォルトでは「Windows Phone 8.1」のデザイン画面と、XAMLコード画面が表示されます(図13)。
では、この画面にツールボックスからコントロールを配置していきましょう。
コントロールの配置
デザイン画面上に配置するコントロール名とその名前は表1のようになります。
コントロール名 | 名前 |
---|---|
TextBlock | 名前なし。「郵便番号検索」のタイトル |
TextBox | TextBox1 |
ListBox | resultListBox |
AppbarButton | okButton |
全てをレイアウトすると図14のようになります。
書き出されるXAMLコードをリスト1のように編集します。
リスト1 書き出され編集されたXAMLLコード(Mainpage.xaml)
(1)Page.Resorucesプロパティ要素内に、ListBoxTemplateというKey名でDataTemplate要素を配置する。その子要素としてStackPanel要素を配置し、背景色に「SlateBlue」、Marginに「10」を指定して余白を設ける。さらにその子要素としてTextBlock要素を配置し、Textプロパティに「zipcode」をバインドする。
再度StackPanel要素を配置し、Orientationプロパティに「Horizontal」を指定してオブジェクトのスタック方向を水平方向とする。その子要素としてTextBlock要素を3つ配置し、Textプロパティに上から順番に「prefecture」、「city」、「town」をバインドしておく。ここで指定した名前は、VBコード内のクラスで定義したプロパティ名だ。
(2)ViewBox要素を配置し、解像度に応じてオブジェクトのサイズが変更されるようにしておく。
(3)Grid要素の背景色を「Black」に指定する。
(4)「郵便番号検索」というタイトル用のTextBlock要素を配置する。
(5)「TextBox1」という名前で、住所を入力するTextBox要素を配置する。
(6)郵便番号の一覧を表示する、名前が「resultListBox」というListBox要素を配置する。ItemTemplateプロパティにStaticResourceを使って、(1)で定義したListBoxTemplateを参照する。
(7)AppbarButton要素を配置し、Iconプロパティに「Accept」、Labelプロパティに「OK」と指定する。このプロパティは図15の方法で設定できる。AppbarButtonを選択し、プロパティの[アイコン]ペインを展開して表示されるSymbolに「Accept」を選択し、[共通]ペイン内のLabelに「OK」と指定する。
<Page x:Class="App1_Common.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:App1_Common" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Page.Resources>(1) <DataTemplate x:Key="ListBoxTemplate">(1) <StackPanel Background="SlateBlue" Margin="10">(1) <TextBlock Text="{Binding zipcode}" Foreground="Gold" FontSize="30"/>(1) <StackPanel Orientation="Horizontal" Width="1110" Margin="10">(1) <TextBlock Text="{Binding prefecture}" FontSize="24" Foreground="White"/>(1) <TextBlock Text="{Binding city}" FontSize="24" Foreground="White"/>(1) <TextBlock Text="{Binding town}" FontSize="24" Foreground="White"/>(1) </StackPanel>(1) </StackPanel>(1) </DataTemplate>(1) </Page.Resources>(1) <Viewbox>(2) <Grid Background="Black">(3) <Grid Height="639" Width="397"> <TextBlock HorizontalAlignment="Left" Height="68" TextWrapping="Wrap" Text="郵便番号検索" VerticalAlignment="Top" Width="315" FontFamily="Meiryo UI" FontSize="50" Margin="52,0,0,0" Foreground="Crimson" FontWeight="Bold"/>(4) <TextBox x:Name="TextBox1" HorizontalAlignment="Left" Height="43" Margin="0,68,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="340" FontFamily="Meiryo UI" FontSize="24"/>(5) <ListBox x:Name="ResultListBox" HorizontalAlignment="Right" Height="518" Margin="0,121,0,0" VerticalAlignment="Top" Width="397" ItemTemplate="{StaticResource ListBoxTemplate}" Background="White" BorderBrush="Black" FontFamily="Meiryo UI" FontSize="36" FontWeight="Bold"/>(6) <AppBarButton x:Name="okButton" HorizontalAlignment="Left" Height="73" Icon="Accept" Label="OK" Margin="323,56,0,0" VerticalAlignment="Top" Width="74" />(7) </Grid> </Grid>(3) </Viewbox>(2) </Page>
では早速プログラムコードを書いていきましょう。
コントロールの配置からも想像できるように、今回のプログラムはWeb APIを使って入力された住所の郵便番号を検索表示させるプログラムです。
入力された住所の郵便番号を表示
今回は、GROOVEの「郵便番号検索API」を使用します。詳細については下記のURLを参照してください。
参考:郵便番号検索API
プログラムコード (MainPage.xaml.vb)
名前空間の読み込み
HTTP 属性のクラスが含まれるSystem.Net.Http名前空間をインポートする。HttpClientクラスを使用するのに必要だ。
次に、コンテキストメニューおよび、メッセージダイアログをサポートするクラスの含まれる、Windows.UI.Popups名前空間をインポートする(リスト2)。
リスト2 (MainPage.xaml.vb)
Imports System.Net.Http Imports Windows.UI.Popups
AddressInfoクラスの定義
AddressInfoクラス内で、文字列型の「zipcode(郵便番号)」、「prefecture(都道府県)」、「city(市)」、「town(町村)」プロパティを定義する(リスト3)。
リスト3
Public Class AddressInfo Property zipcode As String Property prefecture As String Property city As String Property town As String End Class
okButton_Clickメソッドの処理
住所を入力するTextBox1に何も入力されない状態で[OK]ボタンがクリックされた時は、警告メッセージを表示して処理を抜ける。それ以外は以下の処理を行う。
「郵便番号検索API」のリクエストURIを変数myUriに格納し、引数wordに「TextBox1.Text」の値を指定する。引数formatには「xml」を指定して結果がXML形式で返されるよう指定する。
新しいHttpClientクラスのインスタンスmyHttpClientオブジェクトを作成する。HttpClientクラスには、URIで識別されるリソースにHTTP要求を送信し、そのリソースからHTTP応答を受信するための基本グラスが含まれている。
GetStringAsyncメソッドで、指定したURIにGET要求を送信し、非同期操作で応答本体を文字列として返し、その内容を変数resultXmlに格納しておく。
XElement.Parseメソッドで変数resultXmlの内容を文字列として読み込む。
AddressInfoクラスの新しいリストであるmyAddressInfoオブジェクトを作成する。
一度、myAddressInfoオブジェクトをクリアしておく。
Descendantsメソッドで全ての子孫要素「address」の内容を、変数resultに格納しながら以下の処理を繰り返す。
新しいAddressInfoクラスのzipcodeプロパティにzipcode要素の内容を「123-4567」という郵便番号形式で抜き出して指定する。結果XMLでは、通常はzipcod要素の値は「1234567」という形式になっているため、SubStringメソッドで指定した位置から、指定した文字数を取りだして「-(ハイフン)」で連結して指定している。
次にprefectureプロパティに「prefecture要素の値」を指定する。同様に、cityプロパティに「city要素の値」、townプロパティに「town要素の値」を指定して、AddメソッドでmyAddressInfoオブジェクトに追加している。
resultListBoxのItemsSourceプロパティにmyAddressInfoオブジェクトを指定する。
これで、入力した住所に該当する郵便番号が、住所とともに表示される。
非同期処理で行われるため、メソッドの先頭にAsyncを追加する。
具体的なコードはリスト4のようになる。
リスト4
Private Async Sub okButton_Click(sender As Object, e As RoutedEventArgs) Handles okButton.Click If TextBox1.Text = String.Empty Then Dim message As New MessageDialog("住所を入力してください。") Await message.ShowAsync Exit Sub Else Dim myUri As String = String.Format("http://api.postalcode.jp/v1/zipsearch?word={0}&format=xml", TextBox1.Text) Dim myHttpClient As New HttpClient Dim resultXml = Await myHttpClient.GetStringAsync(New Uri(myUri, UriKind.Absolute)) Dim xmldoc As XElement = XElement.Parse(resultXml) Dim myAddressInfo As New List(Of AddressInfo) myAddressInfo.Clear() For Each result In From c In xmldoc.Descendants("address") Select c With myAddressInfo .Add(New AddressInfo With { .zipcode = result.Element("zipcode").Value.Substring(0, 3) & "-" & result.Element("zipcode").Value.Substring(3, 4), .prefecture = result.Element("prefecture").Value, .city = result.Element("city").Value, .town = result.Element("town").Value}) End With Next ResultListBox.ItemsSource = myAddressInfo End If End Sub
以上でプログラムは完成です。しかし、これだけではまだ動作はしません。
App.xaml.vbの編集
実際にプログラムを動かすには、まず「App1_Phone(Windows Phone 8.1)」プロジェクト内のApp.xaml.vbを開き、OnLaunchedイベント内の、リスト5の個所をリスト6のように書き直す必要があります。
リスト5 元のコード App.xaml.vb
If Not rootFrame.Navigate(GetType(MainPage), e.Arguments) Then Throw New Exception("Failed to create initial page") End If
ナビゲーションのパラメーターとして、「MainPage」から「App1_Common.MainPage」に変更して指定します(リスト6)。
リスト6 編集されたコード App.xaml.vb(App_Windows Phone(Windows Phone 8.1))
If Not rootFrame.Navigate(GetType(App1_Common.MainPage), e.Arguments) Then Throw New Exception("Failed to create initial page") End If
「App1_Windows(Windows 8.1)」プロジェクト内のApp.xaml.vbに対しても同じ編集をしておきます(リスト7)。
リスト7 編集されたApp.xaml.vb(App1_Windows(Windows 8.1))
If rootFrame.Content Is Nothing Then rootFrame.Navigate(GetType(App1_Common.MainPage), e.Arguments) End If
これで、全ての設定は完了しました。まずソリューションエクスプローラー内で「App1_Phone(WindowsPhone 8.1)」を選択して、マウスの右クリックで表示されるメニューから、「スタートアッププロジェクトに設定」を選択すると「App1_Phone(Windows Phone 8.1)」の文字が太字に変わります。
ではこれで実行してみましょう(図16)。
次に「Windows 8.1」を「スタートアッププロジェクトに設定」して実行してみましょう(図17)。
通常なら画面の左隅上と右隅上にフレーム レートカウンターの数値が表示されますが、これは各App.xaml.vb内のEnableFrameRateCounterにFalseを指定すると消すことができます。デフォルトではTrueになっています(リスト8)。
リスト8 App.xaml.vb内のフレームレートカウンターの値をFalseに指定する
#If DEBUG Then ' デバッグ中にグラフィックスのプロファイル情報を表示します。 If System.Diagnostics.Debugger.IsAttached Then ' 現在のフレーム レート カウンターを表示します Me.DebugSettings.EnableFrameRateCounter = False End If #End If
■
以上がVisual Basicでユニバーサルアプリを作成する手順です。Visual Basicではユニバーサルアプリが作成できないと思っていたVisual Basicユーザーにとっては大変に嬉しいことです。是非Visual Basicユーザーの皆さんは、この記事を参考にVisual Basicでユニバーサルアプリに挑戦していただきたいと思います。
ちなみに、前回までの記事はC#を使った解説ですので、無料版、Visual Studio 2013 Express for Windowsでも作成が可能です。