「一日一句」完結編 〜リスト選択とソート表示の実装〜
表示ページの実装
入力ページで「一覧」ボタンをタップした時に表示される俳句のファイル・リストの中から年月が選択された時、この表示ページに移動させて、選択された年月の俳句を表示します。
この表示ページでは、今詠んだばかりの最新の俳句をすぐに確認できるように、「▼」ボタンで詠んだ順、「▲」ボタンで新しい順に並べ替える処理も実装します。
表示ページのデザイン(ShowHaiku.xaml)
ソリューションエクスプローラーのプロジェクト名を右クリックして表示される「追加/新しい項目」で、Portrait Pageを追加します。名前は、ShowHaiku.xamlとします。LayoutRootのGridのBackgroundには” #FFFFFFFA”を指定し、StackPanel部分をコメントアウトしておきます。
ツールボックスから、Image、Button、TextBlock、Rectangle、ListBoxコントロールをレイアウトします(図4)。
図4:表示ページにコントロールをレイアウトする(クリックで拡大) |
さらに、ListBoxの子要素としてItemTemplateを定義してStackPanelを配置し、その中に、日本語句と英語句、それらの作成年月日を表示する3個のTextBlock、区切り線として使うRectangleを配置します。
レイアウトした各コントロールのプロパティを調整し、完成したデザイン・コードは、リスト3になります。3個のTextBlockには、日本語句、英語句、俳句の作成年月日のデータをバインドできるようにします(下線部分)。
リスト3 表示ページのデザイン・コード(ShowHaiku.xaml)
<phone:PhoneApplicationPage x:Class="DailyHaiku_in_Japanese.ShowHaiku" 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" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480" shell:SystemTray.IsVisible="True" xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls" 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="15,0,15,0"> <Image Height="60" HorizontalAlignment="Left" Margin="0,15,0,0" Name="HaikuLogo60px" Stretch="Fill" VerticalAlignment="Top" Width="60" Source="/DailyHaiku_in_Japanese;component/Image/HaikuLogo60px.png" /> <!--年月表示--> <TextBlock Height="50" HorizontalAlignment="Left" Margin="130,22,0,0" Name="SelectedMonth" Text="" VerticalAlignment="Top" Width="250" Foreground="#FF00004B" FontSize="32" /> <!--俳句表示--> <Button Height="60" HorizontalAlignment="Left" Margin="300,100,0,0" Name="SortAscendingButton" VerticalAlignment="Top" Width="60" Style="{StaticResource SortAscendingButtonStyle}" /> <Button Height="60" HorizontalAlignment="Left" Margin="390,100,0,0" Name="SortDscendingButton" VerticalAlignment="Top" Width="60" Style="{StaticResource SortDescendingButtonStyle}" /> <Rectangle Height="1" HorizontalAlignment="Left" Margin="0,160,0,15" Name="MyHaikuBorder" VerticalAlignment="Top" Width="450" Fill="#FF237A1E" /> <ListBox Name="MyDailyHaikuListBox" Margin="0,175,0,15" FontSize="24"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="vertical" Name="ShowDataPanel"> <TextBlock Name="Haiku_ja_jpBlock" Text="{Binding 俳句日}" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="0,0,0,0" TextWrapping="Wrap" Foreground="#FF333333" FontSize="26" /> <TextBlock Name="Haiku_enBlock" Text="{Binding 俳句英}" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="48,5,0,0" TextWrapping="Wrap" Foreground="#FF237A1E" FontSize="24" /> <TextBlock Name="Haiku_recordDateBlock" Text="{Binding 年月日}" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="0,5,0,0" Foreground="#FF64BA5E" FontSize="20" TextAlignment="Right" Width="450" /> <Rectangle Height="1" HorizontalAlignment="Left" Margin="0,2,0,15" Name="DailyBorder" VerticalAlignment="Top" Width="450" Fill="#FF64BA5E" /> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> </Grid> </phone:PhoneApplicationPage>
このページでレイアウトしたButtonコントロールのスタイル設定については、リスト4 のコードをApp.xaml内の
リスト4 App.xaml内に追加する、昇順・降順ボタンのスタイル設定(App.xaml)
<Style x:Key="SortAscendingButtonStyle" TargetType="Button"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Grid> <Image x:Name="SortAscendingButtonImage" Source="/DailyHaiku_in_Japanese;component/Image/SortAscendingButton.png" Stretch="Fill"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="SortDescendingButtonStyle" TargetType="Button"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Grid> <Image x:Name="SortDescendingButtonImage" Source="/DailyHaiku_in_Japanese;component/Image/SortDescendingButton.png" Stretch="Fill"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
表示ページのロジック(ShowHaiku.xaml.vb)
この表示ページでは、選択された年月のXMLファイルを読み込んで表示します。その構造は、リスト5のとおりです。
リスト5 表示する俳句のXMLドキュメント(年月.xml)の構造
<?xml version="1.0" encoding="utf-8"?> <俳句集 年月="2012年1月"> <俳句 創作年月日="2012年1月22日" 登録日時="2012/01/22/03:24:07"> <句> 改行された俳句 </句> <ルビ>ルビやコメントなど</ルビ> <英語句> 改行された英語俳句 </英語句> </俳句> ~句の数だけ<俳句>要素、繰り返し~ </俳句集>
このXMLデータをソート表示する処理を記述していきます(リスト6)。
まず、ローカルストレージに保存されているファイルを処理するためにSystem.IO.IsolatedStorage名前空間を、XMLデータを処理するためにSystem.Xml.Linq名前空間をインポートしておきます。
俳句を詠んだ年月日、日本語句、英語句のデータを取得するためのクラスMyTitleDataを作成しておきます。
(1) 選択された年月データを受け取る処理
入力ページ(CreateHaiku.xaml.vb)のMyHaikuMonthListBox_SelectionChangedプロシジャからのパラメータを受け取る処理です。
選択された年月を受け取る変数を宣言し、ListBoxから選択された「年月」を変数ReadMonthに代入します。また、あらかじめソート処理対象のXML木を格納する変数ShowHaikuItemDoc を宣言しておきます。
(2) この表示ページがロードされた時の処理
この表示ページがロードされた時点では、俳句データを昇順表示するため、「昇順」ボタンは使用不可としておきます。
渡されてきた「年月」データに拡張子.xmlを付けて処理対象ファイルとします。選択されたファイルが存在する場合、XML木を読み込み、デフォルトの昇順ソート表示のSortAscendingプロシジャを実行します。
(3) デフォルトの昇順ソート表示の処理
このページの冒頭に記述しているMyTitleDataクラスを使い、新規リストを生成します。
俳句の登録順、すなわち文書順に「俳句」要素を指定して、その「創作年月日」属性値、子要素の「英語句」「句(日本語句)」の内容を取得します。
生成したリストに、各々取得したデータを追加して、ListBoxにデータを適用します。
(4) 降順ソート表示の処理
登録日時の逆順、すなわち逆文書順に「俳句」要素を取得して、そのデータをListBoxに適用して表示します。データの並び順以外は、昇順ソート表示の処理に同じです。
(5) 「昇順ソート」ボタンがタップされた時の処理
「昇順ソート」ボタンを使用不可とし、「降順ソート」ボタンを使用可として、昇順ソート表示の処理のSortAscendingプロシジャを実行します。
(6) 「降順ソート」ボタンがタップされた時の処理
「降順ソート」ボタンを使用不可とし、「昇順ソート」ボタンを使用可として、降順ソート表示の処理のSortDescendingプロシジャを実行します。
リスト6 表示ページのロジック・コード(ShowHaiku.xaml.vb)
Option Strict On Imports System.IO.IsolatedStorage Imports System.IO Imports System.Xml.Linq
俳句データを取得するクラス
Public Class MyTitleData Property 年月日 As String Property 俳句日 As String Property 俳句英 As String End Class Partial Public Class ShowHaiku Inherits PhoneApplicationPage Public Sub New() InitializeComponent() End Sub
(1) CreateHaiku.xaml.vbのMyHaikuMonthListBox_SelectionChangedプロシジャからのパラメータを受け取る処理
'●渡されるパラメータを受け取る変数を宣言 Dim ReadMonth As String = String.Empty '●ListBoxから選択された「年月」を変数に代入 Protected Overrides Sub OnNavigatedTo(ByVal e As System.Windows.Navigation.NavigationEventArgs) Dim MonthParam As IDictionary(Of String, String) = NavigationContext.QueryString ReadMonth = MonthParam("Name") MyBase.OnNavigatedTo(e) End Sub '●ソート処理対象のXML木を格納する変数を宣言 Dim ShowHaikuItemDoc As XDocument
(2) この表示ページがロードされた時の処理
Private Sub ShowHaiku_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded '●デフォルトは昇順表示なので、昇順ボタンを使用不可としておく SortAscendingButton.Opacity = 0.3 SortAscendingButton.IsEnabled = False '●パラメータから渡された年月に拡張子.xmlを付けて処理対象ファイルとする Dim ShowHaikuStorage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication Dim ShowHaikuFilePath As String = Path.Combine("DailyHaiku_in_Japanese_Data", ReadMonth & ".xml") '●タイトルを表示 SelectedMonth.Text = ReadMonth & "の俳句" '●ListBoxから選択されたファイルが存在する場合の処理。ファイルのXML木を読み込み、昇順ソート表示を実行する If ShowHaikuStorage.FileExists(ShowHaikuFilePath) = True Then Dim ShowHaikuStream As IsolatedStorageFileStream = ShowHaikuStorage.OpenFile(ShowHaikuFilePath, FileMode.Open, FileAccess.Read) Dim ShowHaikuReader As StreamReader = New StreamReader(ShowHaikuStream, System.Text.Encoding.UTF8) Dim ShowHaikuReadXmldoc As String = ShowHaikuReader.ReadToEnd ShowHaikuItemDoc = XDocument.Parse(ShowHaikuReadXmldoc) ShowHaikuReader.Close() ShowHaikuStream.Close() SortAscending() Else Exit Sub End If End Sub
(3) デフォルトの昇順ソート表示の処理
Private Sub SortAscending() '●このファイルの冒頭に記述しているMyTitleDataクラスを使い、新規リストを生成 Dim MyKuList As New List(Of MyTitleData) '●登録順、すなわち文書順に「俳句」要素を取得 Dim MyDataQuery As IEnumerable(Of XElement) = From c In ShowHaikuItemDoc.Descendants("俳句") Order By c.@登録日時 Ascending '●「俳句」要素の「創作年月日」属性値、子要素の「英語句」「句」の内容を取得 For Each MyResult In MyDataQuery Dim MyRecordDate As String = MyResult.@創作年月日 Dim MyKuEnglish As String = MyResult.Elements("英語句").Value '●英語句が未入力の場合、改行文字列が入っている可能性があるので、見た目を整えるため空にしておく If MyKuEnglish.Length > 0 Then MyKuEnglish = MyKuEnglish Else MyKuEnglish = String.Empty End If Dim MyData As String = MyResult.Elements("句").Value '●生成したリストに、各々取得したデータを追加 MyKuList.Add(New MyTitleData With {.年月日 = MyRecordDate, .俳句日 = MyData, .俳句英 = MyKuEnglish}) Next '●ListBoxにデータを適用 MyDailyHaikuListBox.ItemsSource = MyKuList End Sub
(4) 降順ソート表示の処理
Private Sub SortDescending() Dim MyKuList As New List(Of MyTitleData) '●登録日時の逆、すなわち逆文書順に「俳句」要素を取得。他の処理は昇順ソート表示に同じ Dim MyDataQuery As IEnumerable(Of XElement) = From c In ShowHaikuItemDoc.Descendants("俳句") Order By c.@登録日時 Descending For Each MyResult In MyDataQuery Dim MyRecordDate As String = MyResult.@創作年月日 Dim MyKuEnglish As String = MyResult.Elements("英語句").Value If MyKuEnglish.Length > 0 Then MyKuEnglish = MyKuEnglish Else MyKuEnglish = String.Empty End If Dim MyData As String = MyResult.Elements("句").Value MyKuList.Add(New MyTitleData With {.年月日 = MyRecordDate, .俳句日 = MyData, .俳句英 = MyKuEnglish}) Next MyDailyHaikuListBox.ItemsSource = MyKuList End Sub
(5)「昇順ソート」ボタンがタップされた時の処理
Private Sub SortAscendingButton_Tap(sender As Object, e As System.Windows.Input.GestureEventArgs) Handles SortAscendingButton.Tap '●「昇順ソート」ボタンを使用不可とし、「降順ソート」ボタンを使用可とする SortAscendingButton.Opacity = 0.3 SortAscendingButton.IsEnabled = False SortDscendingButton.Opacity = 1.0 SortDscendingButton.IsEnabled = True '●昇順ソート表示の処理を実行 SortAscending() End Sub
(6)「降順ソート」ボタンがタップされた時の処理
Private Sub SortDscendingButton_Tap(sender As Object, e As System.Windows.Input.GestureEventArgs) Handles SortDscendingButton.Tap '●「降順ソート」ボタンを使用不可とし、「昇順ソート」ボタンを使用可とする SortDscendingButton.Opacity = 0.3 SortDscendingButton.IsEnabled = False SortAscendingButton.Opacity = 1.0 SortAscendingButton.IsEnabled = True '●降順ソート表示の処理を実行 SortDescending() End Sub End Class