PR

データ保存・bing検索・簡易縦書き機能の実装

2012年4月10日(火)
PROJECT KySS

プログラミングの前に

前回は、俳句・川柳アプリ「一日一句」の企画から設計・デザインまでの作業について解説しました。今回は、実装について解説します。少し長いですが、アプリの中で値を渡して処理している関係上、該当する3つのページのコードを一気に解説しますので、気長にお付き合いください。

サンプル一式は、会員限定特典としてダウンロードできます。記事末尾をご確認ください。

また、このアプリはマーケットプレイスで無料公開されています。
→参照:DailyHaiku(Windows Phone Marketplace)

Windows Phone アプリの開発フレームワークには、XNA Frameworkと Silverlightがあります。XNAはリアルタイムゲーム向けで、SilverlightはRIA向けです。「一日一句」は、Silverlightアプリケーションで、開発言語はVisual Basicです。

本連載では、以前の連載の読者を対象に、実開発からマーケットプレイスへの公開までを解説しています。これからWindows Phone アプリ開発を始める場合は、過去記事「Windows Phone 開発環境の構築と最初のプログラム」を参考に、開発環境を整備してください。

その際、Windows Phone SDK 7.1.1 Update
が発表されていますので、これもインストールしてください。日本語版をインストールする場合は、「Change Language」で Japanese に変更できます。記事中で紹介するアプリは、Windows Phone SDK 7.1の環境で開発しましたが、7.1.1でも問題なく動作します。

なお、筆者の開発環境は、Windows 7 Professional (32 bit) SP1、Visual Studio 2010 Ultimate SP1 (英語版)、Windows Phone SDK 7.1.1 (英語版)、Expression Studio 4(英語版)、Windows Phone Emulator、実機(Windows Phone IS12T)です。画面キャプチャのメニューは英語ですが、日本語版も手順は同じです。

アプリの機能と画面遷移

このアプリの画面遷移

前回記事で述べたとおり、このアプリは4つのページで構成します(図1)。メインページと入力ページはPortrait Page、一画面に内容が収まりそうにない表示ページとヘルプページはPanorama Pageです。

それぞれのページの名前は、図1中の青文字のとおりです。

図1:このアプリのページ構成と画面遷移(クリックで拡大)

各ページに実装する機能

メインページ(季節の選択、ヘルプページへのリンク)
  • 「春」「夏」「秋」「冬」の画像ボタンを配置し、季節を選択できるようにします。季節と月の対応は、おおむね、春(3月、4月、5月)、夏(6月、7月、8月)、秋(9月、10月、11月)、冬(12月、1月、2月)ですが、諸説あります。また、夏に冬の俳句を詠みたい場合や、8月31日23時59分に秋の句を詠むケースも考えられるため、ユーザーが自由に選択できるようにします。
  • 「?」ボタンを置き、ヘルプページにリンクします。
入力ページ(データの入力・検証・保存、季語のbing検索)
  • 俳句と、ルビやコメントを入力できるようにします。
  • 児童の利用を考え、ひらがなのみの字あまり最大19文字まで入力可能とします。
  • 入力文字列は簡易縦書きで表示します。
  • 必須項目と全角半角を検証し、不備がある場合はメッセージを表示します。
  • 「保存」ボタンがタップされた時、年月日、俳句、あればルビの記録された季節別のファイルを、実機内の DailyHaikuData フォルダに保存します。このバージョンは国内向けであり、季語が意味を持つことから、俳句データは季節別のファイルに分けます。データ形式は、投稿のための選定や、句集の編集などに利用できるよう、再利用の容易なXMLです。
  • 「季語検索」ボタンがタップされた時、選択されている季節の季語を、bingで検索させます。
  • 「季節選択」ボタンがタップされた時、メインページに戻って季節を再選択できるようにします。
  • 「一覧」ボタンがタップされた時は、現在選択されている季節の値を表示ページに渡して移動します。
表示ページ(俳句の簡易縦書き表示)
  • 選択されている季節の俳句が1句以上記録されている場合、俳句データを、簡易縦書きで巻物のように画面の右端から表示します(図2)。多数の俳句が記録されている場合でも、左フリックにより最後に保存された最新の句が表示されるため、確認が容易になります。
  • 「一句前へ」ボタンで一句ずつ巻き戻し、「一句目へ」ボタンで先頭の句にジャンプ、「一句後へ」ボタンで一句ずつ早送りします。
  • 「季節選択」ボタンがタップされた時は、メインページに戻って季節を再選択できるようにします。

図2:季節の俳句データを簡易縦書きで巻物のように表示する(クリックで拡大)
ヘルプページ(ヘルプ、ファイルの削除)
  • アプリの説明と操作手順を記載します。
  • 各季節別の記録済み俳句ファイルを削除できるようにします。誤って削除することのないよう、この削除機能はヘルプの最終ページに置きます。

値の渡し方

メインページで選択した季節の値は、入力ページに渡して季語検索と保存処理に利用し、さらに表示ページに渡して、表示するために読み込むXML文書の特定に用います。

例えば「春」を選択した場合、入力ページでは春の季語を検索し、入力した俳句はspring.xmlに保存します。さらに表示ページに移動した時は、spring.xmlのデータを表示するといった具合です。

これらの処理は、図3のように値を受け渡すことで実現しています。

図3:メインページで選択した「季節」データの渡し方(クリックで拡大)

メインページ(季節選択、ヘルプへのリンク)の実装

新規プロジェクトの作成

では、早速開発していきましょう。

「ファイル/ File 」「新規/ New 」「プロジェクト/ Project…」を選択し、開発言語として「Visual Basic」を選択、「Silverlight for Windows Phone」「Windows Phone Application」を選択します。

プロジェクト名は、「DailyHaiku」 としておきます(図4)。

「Windows Phone 7.1」環境の場合は、「Windows Phone 7.0」か、「Windows Phone 7.1」かを選択します。このアプリは 7.1 で作成しています。

図4:「DailyHaiku」プロジェクトを作成する(クリックで拡大)

プロジェクト名を右クリックして表示されるメニューから「追加/新規フォルダ」を選択してフォルダを追加し、名前を「Image」としておきます。このImageフォルダを右クリックして表示されるメニューから「追加/既存のアイテム」を選択して、画像部品一式を追加しておきます(図5)。

※画像ファイルは、ダウンロードできるプロジェクトの中に追加済みです。

図5:Imageフォルダを作成し、アプリ内で使う画像を追加しておく(クリックで拡大)

メインページのデザイン(MainPage.xaml)

まず、背景色を設定しておきます。名前がLayoutRootのGridのBackgroundに“#FFFFFFFA”を指定します。PC用のマルチタッチディスプレイでは淡いベージュに見えるこの色も、実機では一見白にしか見えませんが、白と比べるとまぶしすぎず、落ち着いた感じになります。

今回StackPanelは使わないので、その部分のコードはコメントアウトしておきます(図6)。

図6:StackPanel部分のコードはコメントアウトしておく(クリックで拡大)

次に、ツールボックスからImageコントロールを7個、ドラッグして配置します(図7)。

7個のImageコントロールに名前を付け(図8)、Sourceには、それぞれロゴのタイル、「春」「夏」「秋」「冬」の4つのボタン、「ヘルプ」ボタン、開発者のロゴの画像を指定します(図9)。

図7:ツールボックスから7個のImageコントロールを配置する(クリックで拡大)

図8:Imageコントロールに名前を付ける(クリックで拡大)

図9:それぞれのImageコントロールのプロパティを開き、Sourceに画像を指定する(クリックで拡大)

全てのコントロールのマージンを調整し、完成したデザイン・コードは、リスト1になります。

リスト1 メインページのデザイン・コード(MainPage.xaml)

<phone:PhoneApplicationPage 
  x:Class="DailyHaiku.MainPage"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
  xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
  FontFamily="{StaticResource PhoneFontFamilyNormal}"
  FontSize="{StaticResource PhoneFontSizeNormal}"
  Foreground="{StaticResource PhoneForegroundBrush}"
  SupportedOrientations="Portrait" Orientation="Portrait"
  shell:SystemTray.IsVisible="True" Language="ja-JP">
  
  <!--LayoutRoot is the root grid where all page content is placed-->
  <Grid x:Name="LayoutRoot" Background="#FFFFFFFA">
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
 
    <!--ContentPanel - place additional content here-->
    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
      <Image Height="140" HorizontalAlignment="Left" Margin="155,50,0,0" Name="logoIcon" Stretch="Fill" VerticalAlignment="Top" Width="140" Source="/DailyHaiku;component/Image/dailyHaiku_logo.png" />
      <Image Height="60" HorizontalAlignment="Left" Margin="332,130,0,0" Name="helpIcon" Stretch="Fill" VerticalAlignment="Top" Width="60" Source="/DailyHaiku;component/Image/dailyHaiku_help.png" />
  
      <Image Height="160" HorizontalAlignment="Left" Margin="232,230,0,0" Name="springButton" Stretch="Fill" VerticalAlignment="Top" Width="160" Source="/DailyHaiku;component/Image/dailyHaiku_spring.png" />
      <Image Height="160" HorizontalAlignment="Left" Margin="232,400,0,0" Name="summerButton" Stretch="Fill" VerticalAlignment="Top" Width="160" Source="/DailyHaiku;component/Image/dailyHaiku_summer.png" />
      <Image Height="160" HorizontalAlignment="Left" Margin="62,230,0,0" Name="autumunButton" Stretch="Fill" VerticalAlignment="Top" Width="160" Source="/DailyHaiku;component/Image/dailyHaiku_autumn.png" /> 
      <Image Height="160" HorizontalAlignment="Left" Margin="62,400,0,0" Name="winterButton" Stretch="Fill" VerticalAlignment="Top" Width="160" Source="/DailyHaiku;component/Image/dailyHaiku_winter.png" />
  
      <Image Height="50" HorizontalAlignment="Left" Margin="176,660,0,0" Name="developerLogo" Stretch="Fill" VerticalAlignment="Top" Width="101" Source="/DailyHaiku;component/Image/dailyHaiku_SSDlogo.png" />
  
    </Grid>
  </Grid>
</phone:PhoneApplicationPage>

メインページのロジック(MainPage xaml.vb)

レイアウトができたら、ソリューションエクスプローラー中のMainPage.xamlを展開して表示されるMainPage.xaml.vbの中に、処理を記述していきます。

まず、季節を代入する変数selectSeasonNameを宣言しておきます。

「春」ボタンがタップされた時、変数selectSeasonNameに「spring」という文字列を代入し、inputHaikuプロシジャを実行します。「夏」ボタンがタップされた時は「summer]、「秋」ボタンでは「autumn」、「冬」ボタンでは「winter」をそれぞれ変数selectSeasonNameに代入して、inputHaikuプロシジャを実行します。

inputHaikuプロシジャでは、変数selectSeasonNameに代入されている季節名を、入力ページ(createHaiku)に渡します。この値は、季語検索や保存するファイル名として利用するようになります。

入力ページおよび表示ページから「homeに戻った」という情報が渡された時には、RemoveBackEntryで履歴を除去します(前回記事も参照)。これにより、メインページを表示する前に表示していた他のページがあった場合、実機の「戻る」ボタンを押しても以前のページには戻らず、アプリケーションは終了します。

リスト2 メインページのロジック・コード(MainPage.xaml.vb)

Option Strict On

Partial Public Class MainPage
  Inherits PhoneApplicationPage

  ' Constructor
  Public Sub New()
    InitializeComponent()
  End Sub

  Dim selectSeasonName As String = String.Empty
 
  Private Sub springButton_Tap(sender As System.Object, e As System.Windows.Input.GestureEventArgs) Handles springButton.Tap
    selectSeasonName = "spring"
    inputHaiku()
  End Sub
 
  Private Sub summerButton_Tap(sender As System.Object, e As System.Windows.Input.GestureEventArgs) Handles summerButton.Tap
    selectSeasonName = "summer"
    inputHaiku()
  End Sub
 
  Private Sub autumunButton_Tap(sender As System.Object, e As System.Windows.Input.GestureEventArgs) Handles autumunButton.Tap
    selectSeasonName = "autumn"
    inputHaiku()
  End Sub
 
  Private Sub winterButton_Tap(sender As System.Object, e As System.Windows.Input.GestureEventArgs) Handles winterButton.Tap
    selectSeasonName = "winter"
    inputHaiku()
  End Sub
 
  Private Sub inputHaiku()
    NavigationService.Navigate(New Uri("/createHaiku.xaml?Name=" & selectSeasonName, UriKind.Relative))
    End Sub
 
  Protected Overrides Sub OnNavigatedTo(ByVal e As System.Windows.Navigation.NavigationEventArgs)
    Dim no As Integer = NavigationService.BackStack.Count
    Dim home As String = String.Empty
 
    If NavigationContext.QueryString.TryGetValue("home", CStr(True)) Then
      For i = 0 To no
        NavigationService.RemoveBackEntry()
        MyBase.OnNavigatedTo(e)
      Next
    End If
  End Sub
 
  Private Sub helpIcon_Tap(sender As System.Object, e As System.Windows.Input.GestureEventArgs) Handles helpIcon.Tap
    NavigationService.Navigate(New Uri("/DailyHaikuHelp.xaml", UriKind.Relative))
  End Sub
End Class
Think IT会員限定特典
  • 「一日一句」プロジェクトファイル

四国の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のWebサイトにログインすることでさまざまな限定特典を入手できるようになります。

Think IT会員サービスの概要とメリットをチェック

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