対象読者
このチュートリアルはVisual Studioを使った.NETアプリケーション開発経験があり、かつSilverlightについて基本的な知識を持つ技術者を対象としています。Windows Phone 7のアプリケーション実行基盤はSilvelightがベースとなっているため、Silverlightアプリケーションの開発経験があればWindows Phone 7アプリケーションの開発も多くが共通しているため学習が容易でしょう。
SilverlightについてはMicrosoftのSilverlight公式ページ、およびMSDNの開発者向けドキュメントを参照してください。
開発準備
Windows Phone 7アプリケーションの開発をはじめるには、まずWindows Phone Developer Toolsをインストールします。以下のダウンロードページからvm_web.exeをダウンロードし、インストーラに従って必要なコンポーネントをインストールしてください。現在は英語版しか提供されていないため、本チュートリアルでは英語版のUIで解説を進めます。
Windows Phone Developer ToolsはWindows Phone 7アプリケーション開発に必要な一連のツールをダウンロードし、インストールしてくれます。これには、統合開発環境であるVisual Studio 2010 Express for Windows PhoneとWindows Phone 7エミュレータも含まれています。従って、本チュートリアルのサンプルを動かす範囲ではWindows Phone 7の実機や開発者用のメンバシップ(App Hub)は必要ありません。
ツールおよびWindows Phone 7アプリケーション開発の詳細についてはMicrosoftのWindows Phoneデベロッパーセンターを参照してください。
Windows Phone Developer Toolsを正常にインストールできれば、スタートメニューの「すべてのプログラム」に「Windows Phone Developer Tools」というフォルダが作られているので、この中にあるVisual Studio 2010 Express for Windows Phoneを開いてください。
次に、「File」メニューの「New Project...」メニュー項目を選択し「New Project」ダイアログを開きます。「Installed Templates」から「Visual C#」の「Silverlight for Windows Phone」を選択し、中央に表示されているテンプレートの一覧から「Windows Phone Application」を選択して、サンプルアプリケーション開発用のプロジェクトを作成してください。プロジェクト名や保存場所は任意です。
「OK」ボタンを押してダイアログを閉じると、ソリューションとプロジェクトが生成され、起動までに必要な最小限のコードが自動生成されます。この時点でビルドして実行できます。Visual Studio 2010 Express for Windows PhoneからWindows Phoneアプリケーションを起動する場合、エミュレータで起動するのか、実機で起動するのかを選択できます。エミュレータを使う場合は、ツールバーにあるコンボボックスから「Windows Phone 7 Emulator」を選択している状態で実行してください。
Windows Phone 7実機で実行するにはAppHubへの開発者登録が必要です。AppHubのページに、アカウントの作成やメンバーシップの購入についての詳細が掲載されています。
NetAdvantage for Windows Phone
インフラジスティックス社のNetAdvantageはWindowsフォームやWPF、Silverlightで効率的にデータの視覚化を強化するUIコントロール集です。NetAdvantage for Windows Phoneを用いることで、Silverlightの標準コントロールでは表現が難しいリッチなユーザーエクスペリエンスを提供できるようになります。
NetAdvantage for Windows PhoneはNetAdvantage for Silverlight Data Visualizationをモバイルに特化させたものであり、コンセプトやライブラリの仕様の多くが共通しています。中でも、チャートを表示するXamDataChartは複雑なビジネスデータの関係を視覚化するのに適しており、アプリケーションの生産性やデザイン性を失うことなく、容易にチャートを統合できます。この場ではXamDataChartコントロールをご紹介します。
製品および技術的な詳細は、インフラジスティックスのページをご覧ください。
NetAdvantage for Windows Phoneのコンポーネントを利用するには、コントロールが含まれているアセンブリをプロジェクトの参照に追加しなければなりません。このチュートリアルでは、以下のDLLファイルを参照に追加します。
- InfragisticsWP7.v11.1.dll
- InfragisticsWP7.DataVisualization.v11.1.dll
- InfragisticsWP7.Controls.Charts.XamDataChart.v11.1.dll
この他のコントロールを利用する場合は、同様にコンポーネントが含まれているアセンブリを参照してください。
これで、開発の準備が整いました。実際にNetAdvantage for Windows Phoneのコントロールを使ってみましょう。
ビジネスデータの視覚化
これまで、WebやWindowsフォームで実装される標準的なビジネスアプリケーションでは、多くが表コントロールを好んで採用する傾向にありました。ビジネスデータの多くは列と行の2次元で表現されるものが多く、リレーショナルデータベースのテーブルに対応した表現として、表は最も簡単で理解しやすい視覚表現です。
PCで操作することが前提であれば、表コントロールはシンプルで開発者にとっても利用者にとっても使い慣れたUIでした。グラフなどデータの視覚化を行う場合でも、表が中心となってそこから編集用のフォームやグラフなどの専用のビューを派生させる設計が一般的でしょう。
ところがスマートフォンを対象とした場合、表コントロールは必ずしも使いやすいものではありません。スマートフォンでは解像度に対して画面が小さく、複数のウィンドウを表示することができません。現状のスマートフォンの利用目的の多くが閲覧に特化していることからも、データの抽象的な意味を抽出し、複雑なデータの関係を視覚的に表現することでアプリケーションの価値を高めることができます。
実践ではネットワーク上のサービスにリアルタイムのデータを問い合わせるシナリオが一般的ですが、この場では単純化するためにローカル上で生成したサンプルデータを表示します。サンプルデータは、単純に整数型の値を提供する型を用意し、これのコレクション(IEnumerable)をルート要素のDataContextプロパティに設定します。
WPFやSilverlight世代のフレームワークは、モデル(データ)とビュー(コントロール)を分離することが容易であり、これらを結びつけるバインディングの仕組みが用意されています。NetAdvantage for Windows Phoneにおいてもこの恩恵はそのまま踏襲されています。XamDataChartコントロールを記述したXAMLコードでバインディング元を指定することで、データと画面デザインを分離して開発を進められます。
using System; namespace Sample { public class DataItem { public int Value { get; set; } public DateTime DateTime { get; set; } } }
上記のDataItemクラスが、今回チャートで表示する個々のデータ要素を表すものとします。Valueプロパティがこのデータの値、DateTimeプロパティがこのデータの日付を表現しています。
続いて、アプリケーションのメインページが読み込まれたタイミングで、チャートで表示するDataItemオブジェクトの配列を乱数で生成し、これをDataContextプロパティに設定します。乱数を使っているため、結果は起動毎に異なります。データの日付は、項目ごとに現在の日付からさかのぼって1日間隔としています。
using System; using Microsoft.Phone.Controls; namespace Sample { public partial class MainPage : PhoneApplicationPage { private const int DataCount = 10; private const int MaxValue = 100; public MainPage() { InitializeComponent(); Random random = new Random(); DataItem[] dataSource = new DataItem[DataCount]; for (int i = 0; i < dataSource.Length; i++) { dataSource[i] = new DataItem(); dataSource[i].DateTime = DateTime.Now.AddDays((-dataSource.Length) + i); dataSource[i].Value = random.Next(MaxValue); } DataContext = dataSource; } } }
まだXAMLコードは何も書いていないので画面は一切作られていない状態ですが、これでデータの準備は整いました。後はDataContextに設定されたビジネスデータをどのように視覚化するのかというUIデザインの問題にフェーズを移行します。
XamDataChartコントロールの配置
NetAdvantage for Windows Phoneにおいて、チャートコントロールはInfragistics.Controls.Charts.XamDataChartクラスで表されます。このクラスはSystem.Windows.Controls.Controlクラスから派生したSilverlightコントロールです。よって、他のコントロールやUIElementと同じようにSilverlightアプリケーションのデザインに組み込めます。
XamDataChartコントロールをXAMLコードで記述するには、まずXML名前空間の宣言と同じ方法で、XamDataChartクラスが含まれるアセンブリ内のCLR名前空間に接頭辞を割り当てます。通常は、以下の行をXAMLコードのルート要素(phone:PhoneApplicationPage)に書き加える形となるでしょう。
xmlns:ig="clr-namespace:Infragistics.Controls.Charts;assembly=InfragisticsWP7.Controls.Charts.XamDataChart.v11.1"
これでXAMLコード内においてigという接頭辞からInfragistics.Controls.Charts名前空間にアクセスできます。接頭辞の名前は一意であれば任意です。
<ig:XamDataChart Margin="20"> //各種プロパティの設定... </ig:XamDataChart>
上のコードはXAML上でXamDataChartコントロールを宣言したものです。まだこの時点では、チャートの種類や関連付けるデータを指定していないため機能しません。XamDataChart要素の中に、デザインやデータとの関係を記述していきます。
軸の設定
チャートを表示するには、水平方向(X座標)と垂直方向(Y座標)に沿って表示される軸を設定しなければなりません。軸はAxis抽象クラスによって表され、軸の種類ごとに派生クラスの実装が用意されています。生成した軸を設定するにはXamDataChartクラスのAxesプロパティから軸のコレクションを管理するAxisCollectionオブジェクトを取得し、これにAxisオブジェクトを追加します。
チャートに設定する軸の種類は、後述するシリーズの種類によって制約があります。本稿では、最も標準的なチャートとなるカテゴリシリーズを中心にデザインするため、カテゴリシリーズで使用可能な軸を選択します。カテゴリシリーズで使用する軸は、主に数値を並べるNumericXAxisクラスとNumericYAxisクラスを使った配置となります。このほか、テキストラベルを並べるCategoryXAxis等が用いられます。
-
Axis - Control クラフから派生した軸を表す抽象クラス
-
NumericAxisBase - 数値軸を表す基底抽象クラス
- NumericXAxis - 水平数値軸
- NumericYAxis - 垂直数値軸
-
CategoryAxisBase - カテゴリベース軸の基底抽象クラス
- CategoryXAxis - 水平カテゴリ軸
-
NumericAxisBase - 数値軸を表す基底抽象クラス
一般的なチャートでは水平軸にCategoryXAxisクラスを用いて項目名や日付など非数値のテキスト情報を表示し、垂直軸にNumericYAxisを用いてデータの値を表示することになるでしょう。
軸に表示される数値やテキストのスタイルはAxisクラスのLabelSettingsプロパティを通して設定できます。このプロパティに軸ラベルのスタイル情報を提供するAxisLabelSettingsクラスのオブジェクトを設定することで、ラベルの位置や色、フォントを変更できます。
CategoryAxisBaseクラスでは、カテゴリとして表示するラベルのテキストに関連付けるためのコレクション(IEnumerable)をItemSourceプロパティに設定し、ラベルとして表示する書式文字列をLabelプロパティに設定します。これらの設定によって、対象のデータソースから動的に軸に表示する値をレイアウトしてくれます。Windows Phone 7では、マルチタッチのジェスチャーによるチャートの伸縮がビルドインで有効になっていますが、チャートの伸縮による軸の調整も自動的に行ってくれます。
<ig:CategoryXAxis x:Name="xmXAxis" ItemsSource="{Binding}" Label="{}{DateTime:MM/dd}"> <ig:CategoryXAxis.LabelSettings> <ig:AxisLabelSettings Foreground="White" Location="OutsideBottom" /> </ig:CategoryXAxis.LabelSettings> </ig:CategoryXAxis>
この場では、先ほどDataContextプロパティに設定した配列にバインディングし、水平軸にDateTimeプロパティから得られる値で「月/日」という形で日付を並べるよう指定しています。
同様に垂直軸にもNumericYAxisクラスを設定します。Y軸の値は後述するシリーズにバインディングされている値が割り当てられるため、特に設定するべき項目はありません。LabelSettingsプロパティから、ラベルの色などを調整する程度で良いでしょう。
<ig:NumericYAxis x:Name="xmYAxis"> <ig:NumericYAxis.LabelSettings> <ig:AxisLabelSettings Foreground="Orange" Location="OutsideLeft" FontSize="20" /> </ig:NumericYAxis.LabelSettings> </ig:NumericYAxis>
ここで宣言した軸は、後述するシリーズからバンディングされるため名前を付けておきます。
チャートが持つAxesプロパティはコレクションなので、必要であれば任意の数の軸をチャートに追加することができます。例えば、水平軸の日付に重ねて、別の項目の値を並べることも可能です。
データに応じて柔軟なチャートのレイアウトが可能です。
シリーズ
シリーズはチャート内に表示される1つのデータ列を表します。シリーズはチャート上に表示するデータや軸とバインディングされ、シリーズの種類に応じてデータソースの値とマッピングされた結果がレンダリングされます。
XamDataChartクラスのSeriesプロパティは、シリーズのコレクションを管理するSeriesCollectionクラスのオブジェクトを返します。Seriesプロパティが返したコレクションにシリーズを追加することで、チャート上に1つのデータ列を表示することができます。
シリーズは以下のような種類(グループ)に分けられ、その種類に応じて扱いや軸やデータの制約、レンダリング結果が異なります。
- カテゴリシリーズ
- 散布図シリーズ
- ポーラシリーズ
- 財務シリーズ
本稿では、カテゴリシリーズを中心に解説しますが、すべてのシリーズはSeriesクラスから派生しているため、基本的な扱いは共通しています。ただし、バインディングするプロパティはシリーズの種類に応じて適切に選択しなければなりません。大まかなシリーズの継承関係は、以下のような構造になっています。
-
Series - 全てのシリーズの抽象基底クラス
-
MarkerSeries - マーカーの抽象基底クラス
-
CategorySeries - カテゴリシリーズの抽象基底クラス
- AnchoredCategorySeries - アンカーされたカテゴリシリーズの抽象基底クラス
- ScatterBase - 散布図シリーズの抽象基底クラス
- PolarBase - ポーラシリーズの抽象基底クラス
-
CategorySeries - カテゴリシリーズの抽象基底クラス
- FinancialSeries - 財務シリーズの抽象基底クラス
-
MarkerSeries - マーカーの抽象基底クラス
この場では、このうちのAnchoredCategorySeriesクラスから派生するAreaSeriesクラスを用いてデータを表示してみましょう。AreaSeriesは線グラフの一種をレンダリングしますが、線の下領域を塗りつぶします。
シリーズにデータソースを関連付けるにはSeriesクラスのItemsSourceプロパティにコレクション(IEnumerable)を設定します。この場では、DataContextプロパティに設定したDataItemクラスの配列とバインディングさせます。指定したデータソースから、線グラフの項となるプロパティはAnchoredCategorySeriesクラスのValueMemberPathプロパティに文字列で指定します。
<ig:AreaSeries ItemsSource="{Binding}" ValueMemberPath="Value" XAxis="{Binding ElementName=xmXAxis}" YAxis="{Binding ElementName=xmYAxis}" />
これで、チャートを表示するために必要なデータソースと軸、それに関連付けられたシリーズを作ることができました。これらをまとめたのが以下のXAMLコードとなります。
<phone:PhoneApplicationPage x:Class="Sample.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" xmlns:ig="clr-namespace:Infragistics.Controls.Charts;assembly=InfragisticsWP7.Controls.Charts.XamDataChart.v11.1" 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" > <Grid x:Name="LayoutRoot" Background="Transparent"> <ig:XamDataChart Margin="20"> <ig:XamDataChart.Axes> <ig:CategoryXAxis x:Name="xmXAxis" ItemsSource="{Binding}" Label="{}{DateTime:MM/dd}"> <ig:CategoryXAxis.LabelSettings> <ig:AxisLabelSettings Foreground="White" Location="OutsideBottom" /> </ig:CategoryXAxis.LabelSettings> </ig:CategoryXAxis> <ig:NumericYAxis x:Name="xmYAxis"> <ig:NumericYAxis.LabelSettings> <ig:AxisLabelSettings Foreground="Orange" Location="OutsideLeft" FontSize="20" /> </ig:NumericYAxis.LabelSettings> </ig:NumericYAxis> </ig:XamDataChart.Axes> <ig:XamDataChart.Series> <ig:AreaSeries ItemsSource="{Binding}" ValueMemberPath="Value" XAxis="{Binding ElementName=xmXAxis}" YAxis="{Binding ElementName=xmYAxis}" /> </ig:XamDataChart.Series> </ig:XamDataChart> </Grid> </phone:PhoneApplicationPage>
以上で、チャートを表示するまでに必要最小限のコードが完成しました。プロジェクトをビルドして実行すると、ランダムに生成されたデータがチャートとして表示されることを確認できます。
見た目はシンプルですが、こうしたチャートをデータに依存することなく表示する作業を標準機能だけで行うことは難しく、ここから自由にデータやロジックへの影響を最小限にデザインの調整ができる点がNetAdvantageの大きな魅力となっています。
デザインの改良
データソースを変更することなく、XAMLコードを変更するだけでチャートのレイアウトを変更できます。NetAdvantage for Windows Phoneには豊富なシリーズの種類が用意されているため、シリーズの種類を選択するだけでグラフを変更できます。例えば、上記のXAMLコード内のAreaSeries要素の部分をColumnSeries要素に書き換えるだけで、棒グラフに置き換わります。ColumnSeriesクラスもまた、AreaSeriesクラスと同様にAnchoredCategorySeriesクラスから派生するカテゴリシリーズの一種です。
<ig:ColumnSeries ItemsSource="{Binding}" ValueMemberPath="Value" XAxis="{Binding ElementName=xmXAxis}" YAxis="{Binding ElementName=xmYAxis}" />
同様に、折れ線グラフを表示したければLineSeriesクラスに置き換えるだけです。領域の塗りつぶしが行われないので、加えて線の太さと色を変えてみましょう。線の太さはSeriesクラスのThicknessプロパティから、塗りつぶしはSeriesクラスのBrushプロパティから変更できます。
<ig:LineSeries ItemsSource="{Binding}" ValueMemberPath="Value" XAxis="{Binding ElementName=xmXAxis}" YAxis="{Binding ElementName=xmYAxis}" Thickness="10" Brush="Red" />
XamDataChartクラスのSeriesプロパティはコレクションなので、チャートに対して複数のシリーズを登録することができます。これによって1つのチャートで複数のグラフを並べて表示することができ、複数のデータの関係を分かりやすい形で視覚化できます。上記の列シリーズと折れ線シリーズを同時に表示すると、以下のようなコードになります。
<ig:XamDataChart.Series> <ig:ColumnSeries ItemsSource="{Binding}" ValueMemberPath="Value" XAxis="{Binding ElementName=xmXAxis}" YAxis="{Binding ElementName=xmYAxis}" /> <ig:LineSeries ItemsSource="{Binding}" ValueMemberPath="Value" XAxis="{Binding ElementName=xmXAxis}" YAxis="{Binding ElementName=xmYAxis}" Thickness="10" Brush="Red" /> </ig:XamDataChart.Series>
上の例では同じデータソースを異なる複数のシリーズで表示した例です。当然、異なるデータソースをシリーズに割り当てることもできます。例えば、今年度と昨年度の同時期のデータを重ねて比較するなど、チャートを応用した視覚化によってデータの価値をアプリケーションによって高める工夫が可能になります。