Chartコントロールを使ってWindows Phoneに棒グラフを表示する

2012年2月20日(月)
PROJECT KySS

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

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

リスト3  (DataInPage.xaml.vb)

Option Strict On
Imports System.Xml.Linq
Imports System.IO

仮想ファイルシステムを作成および使用するための型が含まれている、System.IO.IsolatedStorage名前空間をインポートします。分離ストレージによって、安全なクライアント側のストレージが提供されます。

Imports System.IO.IsolatedStorage

Partial Public Class DataInPage
  Inherits PhoneApplicationPage

  Public Sub New()
    InitializeComponent()
  End Sub

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

「記録日」の入力欄に、現在の日付を入力しておきます。

変数storageを、ファイルとディレクトリを格納している分離ストレージ領域を表すIsolateStorageFileクラスとして宣言します。

RecordBloodPressureというフォルダが存在しない場合は、CreateDirectoryメソッドでディレクトリを作成します。

Path.Combineで、RecordBloodPressureというフォルダ名と、BloodPressure.xmlというXMLファイルを連結し、filePath変数に格納しておきます。

FileExistsメソッドでXMLファイルが存在しているかどうかをチェックし、存在している場合は以下の処理を実行します。

IsolatedStorageFileクラスのOpenFileメソッドでRecordBloodPressureフォルダ内のBloodPressure.xmlファイルを、指定したファイルアクセスを使用して指定したモードでファイルを開きます。開いたファイルをStreamReaderで読み込みます。ReadToEndメソッドでファイルの最後まで読み取り、変数readXmldoc変数に格納しておきます。読み込んだXMLテキストをParseメソッドでXElementとして読み込みます。要素の子要素を選択するクエリを定義します。要素の個数が0より大きい場合、つまり、血圧のデータが記録されている場合は、[データ一覧]ボタンの使用を可能にします。それ以外の場合は、使用を不可としておきます。

  Protected Overrides Sub OnNavigatedTo(e As System.Windows.Navigation.NavigationEventArgs)
    recorddateTextBox.Text = DateTime.Now.ToShortDateString
 
    Dim storage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication
    If storage.DirectoryExists("RecordBloodPressure") = False Then
        storage.CreateDirectory("RecordBloodPressure")
    End If
    Dim filePath As String = Path.Combine("RecordBloodPressure", "BloodPressure.xml")
    If storage.FileExists(filePath) = True Then
      Dim myStream As IsolatedStorageFileStream = storage.OpenFile(filePath, FileMode.Open, FileAccess.Read)
      Using reader As StreamReader = New StreamReader(myStream, System.Text.Encoding.UTF8)
        Dim readXmldoc As String = reader.ReadToEnd
        Dim doc As XElement = XElement.Parse(readXmldoc)
        Dim query = From c In doc.Descendants("情報") Select c.Element("記録日")
        If query.Count > 0 Then
            ichiranButton.IsEnabled = True
        Else
            ichiranButton.IsEnabled = False
        End If
      End Using
    End If
 
    MyBase.OnNavigatedTo(e)
  End Sub

[記録]ボタンがタップされた時の処理

Path.Combineで、RecordBloodPressureというフォルダ名と、BloodPressure.xmlというXMLファイルを連結し、filePath変数に格納しておきます。変数storageを、ファイルとディレクトリを格納している分離ストレージ領域を表すIsolateStorageFileクラスとして宣言します。

分離ストレージ内のファイルを表すIsolatedStorageFileStreamクラス用オブジェクト変数_myStreamを用意し、IsolatedStorageFileクラスのOpenFileメソッドでRecordBloodPressureフォルダ内のBloodPressure.xmlファイルを、指定したファイルアクセスを使用して指定したモードでファイルを開きます。開いたファイルをStreamReaderで読み込みます。ReadToEndメソッドでファイルの最後まで読み取り変数readXmldoc変数に格納しておきます。読み込んだXMLテキストをParseメソッドでXElementとして読み込みます。

読み込んだXMLファイルの要素の子要素である要素の一番最後に記録された日付を取得します。変数date1に「記録日」のTextBoxに入力されている日付を、日付型に変換して格納します。変数date2に要素の一番最後に記録された日付を、日付型に変換して格納します。

Date.Compareメソッドでdate1とdate2を比較します。date1(recorddateTextBox.Text)がdate2(変数dateQueryStr)の値より小さい場合は、-1を返しますので、この値を元に警告メッセージを表示して処理を抜けます。血圧が既に記録されている記録日より、前日の「記録日」にデータが入力されようとすると、警告メッセージが出て記録できないということです。

System.Convert.ToInt16メソッドで「最高血圧」と「最低血圧」に入力されたString 形式の数値を、それと等価な 16 ビット符号付け整数に変換します。ここに数値以外の文字列を入力すると例外が発生しますので、その時、警告メッセージを表示します。

「最高血圧」と「最低血圧」のデータが未入力の場合は処理を抜けます。入力されている場合は、以下の処理を行います。

RecordBloodPressureというフォルダが存在しない場合は、CreateDirectoryメソッドでディレクトリを作成します。

FileExistsメソッドでXMLファイルが存在しているかどうかをチェックし、存在していない場合は以下の処理を実行します。

Visual Basic の埋め込み式を用いて、XML宣言とルート要素、その子要素として、要素の子要素として、、、を作成し、内容テキストとして、埋め込み式の構文である を用いて各TextBoxに入力された値を指定します。これは ASP.NET で使用される構文と同じです。

分離ストレージ内のファイルを表すIsolatedStorageFileStreamクラス用オブジェクト変数streamを用意し、IsolatedStorageFile.CreateFileメソッドで、分離ストレージ内にfilePath変数の持っているフォルダ名付けXMLファイルを作成します。CreateFileメソッドでフォルダとXMLが作成されましたので、RecordBloodPressureフォルダ内にBloodPressure.xmlファイルが存在する場合は、新しいStreamWriter を作成し、IsolatedStorageFile.OpenFileメソッドで、指定したファイルアクセスを使用して指定したモードでファイルを開き、初期化します。Writeメソッドで埋め込み式のXMLをストリームに書き込みます。保存した旨のメッセージを表示します。

次は、最初からRecordBloodPressureフォルダ内にBloodPressure.xmlファイルが存在する場合の処理です。

分離ストレージ内のファイルを表すIsolatedStorageFileStreamクラス用オブジェクト変数myStreamを用意し、IsolatedStorageFileクラスのOpenFileメソッドでRecordBloodPressureフォルダ内のBloodPressure.xmlファイルを、指定したファイルアクセスを使用して指定したモードでファイルを開きます。開いたファイルをStreamReaderで読み込みます。ReadToEndメソッドでファイルの最後まで読み取り変数readXmldoc変数に格納しておきます。読み込んだXMLテキストをParseメソッドでXElementとして読み込みます。

追加する要素とその子要素を、埋め込み式を用いて生成し、各要素の値に各TextBoxに入力された値を指定します。新しく生成したXML要素を、読み込んだXMLにAddメソッドで追加します。IsolatedStorageFileStreamを閉じます。

BloodPressure.xmlファイルが存在する場合は、新しいStreamWriter 生成し、IsolatedStorageFile.OpenFileメソッドで、指定したファイルアクセスを使用して指定したモードでファイルを開き、初期化します。Writeメソッドで新しいXML要素の追加されたXMLを、ストリームに書き込みます。[データ一覧]ボタンの使用を可能にします。保存した旨のメッセージを表示します。

  Private Sub recordButton_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles recordButton.Click
    Dim myDoc As XElement
    Dim filePath As String = Path.Combine("RecordBloodPressure", "BloodPressure.xml")
    Dim storage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication
    Dim _myStream As IsolatedStorageFileStream = storage.OpenFile(filePath, FileMode.Open, FileAccess.Read)
    Using reader As StreamReader = New StreamReader(_myStream, System.Text.Encoding.UTF8)
      Dim readXmldoc As String = reader.ReadToEnd
      myDoc = XElement.Parse(readXmldoc)
    End Using
     
    Dim dateQueryStr As String = myDoc.Descendants("情報").Elements("記録日").Last.Value
    
    Dim date1 As Date = Date.Parse(recorddateTextBox.Text)
    Dim date2 As Date = Date.Parse(dateQueryStr)
 
    Dim result As Integer = Date.Compare(date1, date2)
  
    If result = -1 Then
      MessageBox.Show("現在記録済みの日付より前日のデータは入力できません")
      Exit Sub
    End If
   
    Try
      Dim high As Integer = System.Convert.ToInt16(highTextBox.Text)
      Dim low As Integer = System.Convert.ToInt16(lowTextBox.Text)
    Catch
      MessageBox.Show("数値を入力してください。")
      Exit Sub
    End Try
 
    If highTextBox.Text = String.Empty OrElse lowTextBox.Text = String.Empty Then
      Exit Sub
    Else
      If storage.DirectoryExists("RecordBloodPressure") = False Then
          storage.CreateDirectory("RecordBloodPressure")
      End If
 
      If storage.FileExists(filePath) = False Then
          Dim xmldoc As XDocument = <?xml version="1.0" encoding="utf-8"?>
                                    <血圧記録>
                                      <情報>
                                        <記録日><%= recorddateTextBox.Text %></記録日>
                                        <最高血圧><%= highTextBox.Text %></最高血圧>
                                        <最低血圧><%= lowTextBox.Text %></最低血圧>
                                      </情報>
                                    </血圧記録>
 
          Using stream As IsolatedStorageFileStream = storage.CreateFile(filePath)
          End Using
          'stream.Dispose()
          If storage.FileExists(filePath) = True Then
              Using writer As StreamWriter = New StreamWriter(storage.OpenFile(filePath, FileMode.Open, FileAccess.Write))
                writer.Flush()
                writer.Write(xmldoc.ToString)
                MessageBox.Show("保存しました。")
                ichiranButton.IsEnabled = True
              End Using
          End If
        Else
          Dim myStream As IsolatedStorageFileStream = storage.OpenFile(filePath, FileMode.Open, FileAccess.Read)
          Using reader As StreamReader = New StreamReader(myStream, System.Text.Encoding.UTF8)
            Dim readXmldoc As String = reader.ReadToEnd
            Dim doc As XElement = XElement.Parse(readXmldoc)
            
            Dim query = From c In doc.Descendants("情報") Where c.Element("記録日").Value.Equals(recorddateTextBox.Text) Select c
  
            If query.Count > 0 Then
              MessageBox.Show("血圧は記録済みです。")
              Exit Sub
            End If
 
            Dim addXml As XElement = <情報>
                                       <記録日><%= recorddateTextBox.Text %></記録日>
                                       <最高血圧><%= highTextBox.Text %></最高血圧>
                                       <最低血圧><%= lowTextBox.Text %></最低血圧>
                                     </情報>
 
            doc.Add(addXml)
            'reader.Dispose()
            myStream.Close()
 
            If storage.FileExists(filePath) = True Then
                Using writer As StreamWriter = New StreamWriter(storage.OpenFile(filePath, FileMode.Open, FileAccess.Write))
                  writer.Flush()
                  writer.Write(doc.ToString)
                  'writer.Close()
                  MessageBox.Show("保存しました。")
                  ichiranButton.IsEnabled = True
                End Using
            End If
          End Using
        End If
      End If
    End Sub

[データ一覧]ボタンがタップされた時の処理

Mainpage.xamlに遷移します。

    Private Sub ichiranButton_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles ichiranButton.Click
      NavigationService.Navigate(New Uri("/MainPage.xaml", UriKind.Relative))
    End Sub
End Class
  • 「Chartコントロールを使ってWindows Phoneに棒グラフを表示する」サンプルプログラム

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

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