まさに生まれ変わったSPREADであり、これからのグレープシティを担うコンポーネントに仕上がっています。今回は、新機能として実装された1レコード複数行表示機能を使い、価格比較サイトの情報を表示する方法を取り上げてみたいと思います。
準備
「SPREAD for WPF 1.0J」のインストール
「SPREAD for WPF 1.0J」では、インストーラも一新され、さらに使いやすくなっています。新しいインストーラで気に入ったのは、インストールフォルダの指定方法です。
グレープシティのインストーラのデフォルト動作は、「C:\Program Files (x86)」フォルダ配下に製品名フォルダを作ります。個人的な感覚として「C:\Program Files (x86)」フォルダの配下に、製品名フォルダを直接作成するのに少々抵抗感があったので、インストールするときはデフォルトから「C:\Program Files (x86)\GrapeCity」フォルダ配下に製品フォルダを指定するように変更しています。
今までのインストーラでもこのような変更は可能でしたが、インストール先を変えようとすると最後の製品名部分の指定は手打ちするしかありませんでした。新インストーラーでは製品名フォルダが常に最後に自動的についてくれるため、非常に簡単にデフォルト以外のインストール先を指定できます。
WPFプロジェクトの作成
「SPREAD for WPF」のインストールが完了したら、Visual Studioを起動して、WPFアプリケーションの新規作成を行います。
ツールボックスへの追加
ツールボックスを右クリックして[タブの追加]を選択し、「GrapeCity WPF」タブを追加します。次に「GrapeCity WPF」タブの下を右クリックして[アイテムの選択]を選択し、ダイアログから「GcSpreadGrid」をチェックして追加します。ツールボックスに「GcSpreadGird」が追加されれば準備完了です。一度、Visual Studioを終了しておくと良いでしょう。
「SPREAD for WPF 1.0J」のコンポーネント名が「GcSpread」ではなく「GcSpreadGrid」となっている点も、このコンポーネントが単なるSPREADの焼き直しではないという意味が含まれていると思います。
GcSpreadGridを配置
WPFアプリケーションのプロジェクトが生成されたら、MainWaindow.xamlをデザイナで開きます。
ウィンドウデザイナでの作業
次にツールボックスにある「GcSpreadGrid」アイコンを、デザイナ上のウィンドウにドラッグ&ドロップします。
実行
この状態でどのような表示になるか実行してみましょう。
SpreadGridデザイナの実行
ウィンドウデザイナでの作業
SPREADのデザインはプログラムから行っても良いのですが、専用デザイナを使うことで生産性の向上も含めて本領を発揮します。このバージョンでは、デザイナの名称も「SpreadGridデザイナ」となっています。
SpreadGridデザイナは、Visual Studio上でSPREADを右クリックし、[SpreadGridデザイナ]を選択して起動します。
また、SpreadGridデザイナはモーダルウィンドウとして起動するので、SpreadGridデザイナの操作中はVisual Studioを操作できません。
SpreadGridデザイナでの作業
SpreadGridデザイナでの基本的な流れの一つとして、列単位に設定を行った後に必要に応じて特別な行を追加していきます。今回は特別な行はありませんが、まずは列の設定を行ってから、複数行対応を行うという手順を取りたいと思います。
列の設定
今回のサンプルでは、JSONで取得したデータを設定したリストをSPREADに連結します。
そこでSpreadGridデザイナを使って、列に対するDataFieldに対してリストの要素名を設定します。同時にHeaderプロパティに列名をいれておくと良いでしょう。
一通り列の設定が終わったら[適用して終了]すれば、SpreadGridデザイナでの設定内容がVisual Studio側に反映されます。
ウィンドウデザイナでの確認
SpreadGridデザイナでの作業結果が、XAMLでどのように表現されているのか確認してみましょう。
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sg="http://schemas.grapecity.com/windows/spreadgrid/2012" Title="MainWindow" Height="350" Width="525"> <Grid> <sg:GcSpreadGrid HorizontalAlignment="Left" VerticalAlignment="Top" DocumentUri="/CZ1211SpreadWPF;component/document1.sgxml" /> </Grid> </Window>
XAMLコードをみて驚くのが、今回の設定を反映したものがどこにもないように見える点でしょう。SpreadGridデザイナでの設定は、XAML上ではなくDocumentUriで指定したsgxml(SpreadGridXML)ファイルに記録されます。このように別ファイルにすることで、XAML定義の肥大化を防ぎながらきめ細かなSpreadデザインが実現できているといえるでしょう。
データの作成
画面の設定が終わったので、価格比較サイトから情報を取得してリストを作成しましょう。今回は検索用APIがJSONで公開されているconeco.netを利用しました。利用に際しては利用者登録をしてAPIキーを取得しておく必要があります。サンプルコードではこの部分でコンパイルエラーがでるようにしてありますので、取得して行末のセミコロン(;)を削除して対応してください。
なお、Proxyサーバーを介したネットワークでは、データの取得がうまくいかないことがあるようです。
coneco.netでAPIを使うためには次のような手順でAPIキーを取得して、そのAPIキーを指定してアクセスする必要があります。
- https://www.coneco.net/api/ にアクセスしてメールアドレスとパスワードを設定
- 本登録用URLのお知らせメールに書かれたAPIキー取得用URLをクリック
- APIキー発行完了のお知らせメールにある「あなたのAPIキー」をプログラムにセット
商品検索結果の形式
coneco.netの製品検索結果はJSON形式で取得できます。返されてくるJSON形式に合わせたクラス定義は次のようになります。
Public Class ResultContext <System.Runtime.Serialization.DataContract()> _ Public Class TResult <System.Runtime.Serialization.DataMember()> _ Public Property Item As List(Of TItem) End Class <System.Runtime.Serialization.DataContract()> _ Public Class TItem <System.Runtime.Serialization.DataMember()> _ Public Property ComId As String : (略) : <System.Runtime.Serialization.DataMember()> _ Public Property Specifications As List(Of TSpecifications) End Class <System.Runtime.Serialization.DataContract()> _ Public Class TSpecifications <System.Runtime.Serialization.DataMember()> _ Public Property Id As String <System.Runtime.Serialization.DataMember()> _ Public Property Title As String <System.Runtime.Serialization.DataMember()> _ Public Property Spec As String End Class End Class
APIの呼び出し
商品検索APIは、「http://api.coneco.net/cws/v1/SearchProducts_json?apikey=xxxx&categoryId=10120&sort=ranking」のようなURLにアクセスして行います。
キーワード検索を行うときは、このURLの後ろに、「&freeword=キーワード」のパラメータを付与します。
このようにして組み立てたURLを指定し、GetStringAsyncを実行してJSON形式のデータを受信します。
Public Class ConecoContext Public Property Ranking As String Public Property ComId As String Public Property Name As String Public Property Manufacturer As String Public Property LowestPrice As String Public Property HighestPrice As String Public Property CPU As String Public Property Disk As String Public Property Memory As String Public Property Display As String Public Property ImageUrl As String Public Property Img As BitmapImage End Class Public Class ConecoModel Implements INotifyPropertyChanged Public Property Items As New List(Of ConecoContext) : (略) : Private Sub GetItemContext(ByVal result As String) Using Stream As New MemoryStream(System.Text.Encoding.UTF8.GetBytes(result)) Dim serializer As New DataContractJsonSerializer(GetType(ResultContext.TResult)) Dim jsonDataValue As ResultContext.TResult = CType(serializer.ReadObject(Stream), ResultContext.TResult) Me.Items = (From item In jsonDataValue.Item Where item.SellerCount > 0 Order By CType(IIf(item.CategoryRanking.Length = 0, Integer.MaxValue, item.CategoryRanking), Integer) Select New ConecoContext With { .Ranking = item.CategoryRanking, .ComId = item.ComId, .Name = item.Name, .Manufacturer = item.Manufacturer, .LowestPrice = item.LowestPrice, .HighestPrice = item.HighestPrice, .CPU = item.Specifications(0).Spec, .Disk = item.Specifications(2).Spec, .Memory = item.Specifications(3).Spec, .Display = item.Specifications(4).Spec, .ImageUrl = item.ImageUrl, .Img = New BitmapImage(New Uri(item.ImageUrl)) }).ToList End Using End Sub : (略) : End Class
このコードにより、Itemsプロパティに画面表示に必要なデータがセットできます。
画面側コード
MainWindow.xaml.vbでは、ConecoModelと連結したMainViewModelをDataContextに割り当てるコードだけが必要です。
Class MainWindow Private WithEvents ViewModel As New MainViewModel Public Sub New() InitializeComponent() Me.DataContext = Me.ViewModel Me.ViewModel.GetItems.Execute("") End Sub End Class
あとはXAML定義でSPREADにItemsをBindingしましょう。
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sg="http://schemas.grapecity.com/windows/spreadgrid/2012" Title="MainWindow" Height="350" Width="525"> <Grid> <sg:GcSpreadGrid HorizontalAlignment="Left" VerticalAlignment="Top" DocumentUri="/CZ1211SpreadWPF;component/document1.sgxml" ItemsSource="{Binding Items}" /> </Grid> </Window>
実行
この状態でどのような表示になるか実行してみましょう。
正しい結果が表示されているように見えますが、よく見るとタイトルがプロパティ名に変わっていますし、2列目も商品画像の列ではありません。
これはSPREADのAutoGenerateColumnsプロパティの省略値が、Trueであることと関係しています。このプロパティは、割り当てられたリストの各要素を自動的にSPREADの列に展開してくれる優れものですが、今回のケースではこの機能が働くのは望むべき動きではありません。そこで、AutoGenerateColumnsにFalseを設定して動きを止めたいと思います。
WindowsフォームではプログラムコードでFalseを設定していたと思いますが、WPFではXAMLで定義するのが良いでしょう。
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sg="http://schemas.grapecity.com/windows/spreadgrid/2012" Title="MainWindow" Height="350" Width="525"> <Grid> <sg:GcSpreadGrid HorizontalAlignment="Left" VerticalAlignment="Top" DocumentUri="/CZ1211SpreadWPF;component/document1.sgxml" ItemsSource="{Binding Items}" AutoGenerateColumns="False" /> </Grid> </Window>
それでは再度実行してみましょう。
今度は設定したヘッダなども、意図した通りにデータが表示されました。
とはいえ、ランキングや最低価格、最高価格などは右寄せにしたいですし、製品画像はURLではなく、画像を表示したいところです。次はこの辺りを設定してみましょう。
セル型の設定
今回の特集では、SPREADに対して徹底的にセルではなく列でさまざまな設定を施します。これはSPREADがセル単位に細かく制御できるという特徴があるため、どうしても公式の情報がセル単位での方法に偏っているためです。
今手元にあるアプリの状態を再度確認してみましょう。現状は、商品情報サイトからデータを取得し、列ごとにBinding設定をしたSPREADに無事表示できたという地点になります。
それでは、データの特性に合わせて列の特性を設定しましょう。
SpreadGridデザイナでの作業
SpreadGridデザイナを起動して、[ランキング]列タイトルをクリックします。[配置]リボングループで、[左寄せ]アイコンをクリックします。同様に[最低価格]列、[最高価格]列についても同じ操作を行います。
[製品画像]列については、[セル型]リボングループで[イメージ型セル]アイコンをクリックして列全体をイメージ型にします。
実行
この状態でどのような表示になるか実行してみましょう。
左寄せ、画像表示共に意図した表示になっています。
テンプレートデザイナによる複数行表示の設定
1行での表示がほぼ意図した状態になったところで、いよいよこのデータを1レコード複数行表示に変更してみましょう。
SpreadGridデザイナでの作業
SpreadGridデザイナの[ツール]リボングループで、[テンプレートデザイナ]アイコンをクリックします。すると今までの表示が[SpreadGrid]ペインと[デザイナ]ペインに分かれて表示されます。[デザイナ]ペインには、先頭4列がサンプルとして1レコード2行2列のフォーマットにデザインされています。このデフォルトでサンプルデザインが表示される仕様は非常に親切な優れものです。
[デザイナ]ペインの最上部には、1レコードの配置デザインに使う設定アイコンが並んでいます。
このアイコンの内容からも分かるように、テンプレートの役目はセルの配置に特化しています。よって、列全体も含めセルに関する左寄せなどはテンプレート側ではなく、[SpreadGrid]ペイン側で設定しておく必要があるのです。
[デザイナ]ペインのセルには右上にマークがついています。このマークが事前に設定済みでまだ割り当てていない列を選択できるマークです。
とても単純ですが、[デザイナ]ペインでのデザインを非常に使いやすくしてくれる機能です。
実行
この状態でどのような表示になるか実行してみましょう。
残念ながらまったく変化がありません。どこが悪いのでしょうか。
もう一度、SpreadGridデザイナに戻って画面を確認してみると、[デザイナ]ペインのメニューに[テンプレートを使用]というものがあります。
ためしに[テンプレートを使用]をクリックしたところ、[SpreadGrid]ペインの表示もテンプレートに合わせたものに変化し、また適用して終了したところVisual Studioのウィンドウデザイナでの表示もテンプレートに合わせたものに変わりました。
この設定を行って実行してみると、1レコード複数行表示が無事完成しました。
まとめ
SPREAD for WPF 1.0Jは、今までのSPREAD製品の中でも一番使いやすいSPREAD製品であるように感じます。これはWPFの表現力という点もあるでしょうし、自分のプログラミングノウハウの変化という主観的な面も多く影響していると思えるのですが、SpreadGridデザイナの使い方も含めて、使いたい機能が分かりやすく実装されているというのが初見での感想です。今回実装が見送られた機能を使っていた人には反発も生じるかも知れませんが、機能のスリムアップとそれと(開発リソース的に)バーターであるであろう1レコード複数行表示の導入という大英断には素直に拍手を送りたいと思います。
カタログスペックレベルで○を多くつけるよりも、一つ一つの○が「これがあってよかった」と何重丸にもしたいくらいの機能が並んでいるコンポーネントを目指してもらいたいと思います。