SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

現役エンジニア直伝! 「現場」で使えるコンポーネント活用術(SPREAD)

いよいよ登場! WPFをブレイクスルーする魅惑のコンポーネント「SPREAD for WPF 1.0J」

「SPREAD for WPF 1.0J」の1レコード複数行表示機能

  • このエントリーをはてなブックマークに追加

 グレープシティのSPREADといえば、グレープシティの代表的なコンポーネントの一つです。そのSPREADのWPF版がいよいよ登場しました。もちろん、Windows 8デスクトップやVisual Studio 2012に対応していることは言うまでもありません。そればかりか単純なWPFへの移植ではなく機能の取捨択一を行い、よりWPFに合わせた形にブラッシュアップしました。身軽になったリソースを、従来はMultiRowという別製品で提供されていた「1レコード複数行表示機能」の実装に割り当てるという大英断すら行われています。

  • このエントリーをはてなブックマークに追加

 まさに生まれ変わったSPREADであり、これからのグレープシティを担うコンポーネントに仕上がっています。今回は、新機能として実装された1レコード複数行表示機能を使い、価格比較サイトの情報を表示する方法を取り上げてみたいと思います。

準備

「SPREAD for WPF 1.0J」のインストール

 「SPREAD for WPF 1.0J」では、インストーラも一新され、さらに使いやすくなっています。新しいインストーラで気に入ったのは、インストールフォルダの指定方法です。

図1 SPREAD for WPF 1.0のインストール
図1 SPREAD for WPF 1.0のインストール

 グレープシティのインストーラのデフォルト動作は、「C:\Program Files (x86)」フォルダ配下に製品名フォルダを作ります。個人的な感覚として「C:\Program Files (x86)」フォルダの配下に、製品名フォルダを直接作成するのに少々抵抗感があったので、インストールするときはデフォルトから「C:\Program Files (x86)\GrapeCity」フォルダ配下に製品フォルダを指定するように変更しています。

 今までのインストーラでもこのような変更は可能でしたが、インストール先を変えようとすると最後の製品名部分の指定は手打ちするしかありませんでした。新インストーラーでは製品名フォルダが常に最後に自動的についてくれるため、非常に簡単にデフォルト以外のインストール先を指定できます。

WPFプロジェクトの作成

 「SPREAD for WPF」のインストールが完了したら、Visual Studioを起動して、WPFアプリケーションの新規作成を行います。

図2 WPFアプリケーションの新規作成
図2 WPFアプリケーションの新規作成

ツールボックスへの追加

図3 ツールボックスへの追加
図3 ツールボックスへの追加

 ツールボックスを右クリックして[タブの追加]を選択し、「GrapeCity WPF」タブを追加します。次に「GrapeCity WPF」タブの下を右クリックして[アイテムの選択]を選択し、ダイアログから「GcSpreadGrid」をチェックして追加します。ツールボックスに「GcSpreadGird」が追加されれば準備完了です。一度、Visual Studioを終了しておくと良いでしょう。

 「SPREAD for WPF 1.0J」のコンポーネント名が「GcSpread」ではなく「GcSpreadGrid」となっている点も、このコンポーネントが単なるSPREADの焼き直しではないという意味が含まれていると思います。

GcSpreadGridを配置

 WPFアプリケーションのプロジェクトが生成されたら、MainWaindow.xamlをデザイナで開きます。

ウィンドウデザイナでの作業

 次にツールボックスにある「GcSpreadGrid」アイコンを、デザイナ上のウィンドウにドラッグ&ドロップします。

図4 GcSpreadGridを配置
図4 GcSpreadGridを配置

実行

 この状態でどのような表示になるか実行してみましょう。

図5 配置直後の実行
図5 配置直後の実行

SpreadGridデザイナの実行

ウィンドウデザイナでの作業

 SPREADのデザインはプログラムから行っても良いのですが、専用デザイナを使うことで生産性の向上も含めて本領を発揮します。このバージョンでは、デザイナの名称も「SpreadGridデザイナ」となっています。

 SpreadGridデザイナは、Visual Studio上でSPREADを右クリックし、[SpreadGridデザイナ]を選択して起動します。

図6 SpreadGridデザイナの実行
図6 SpreadGridデザイナの実行

 また、SpreadGridデザイナはモーダルウィンドウとして起動するので、SpreadGridデザイナの操作中はVisual Studioを操作できません。

SpreadGridデザイナでの作業

 SpreadGridデザイナでの基本的な流れの一つとして、列単位に設定を行った後に必要に応じて特別な行を追加していきます。今回は特別な行はありませんが、まずは列の設定を行ってから、複数行対応を行うという手順を取りたいと思います。

列の設定

 今回のサンプルでは、JSONで取得したデータを設定したリストをSPREADに連結します。

 そこでSpreadGridデザイナを使って、列に対するDataFieldに対してリストの要素名を設定します。同時にHeaderプロパティに列名をいれておくと良いでしょう。

図7 DataFieldの設定
図7 DataFieldの設定

 一通り列の設定が終わったら[適用して終了]すれば、SpreadGridデザイナでの設定内容がVisual Studio側に反映されます。

ウィンドウデザイナでの確認

 SpreadGridデザイナでの作業結果が、XAMLでどのように表現されているのか確認してみましょう。

リスト1 列設定実施後の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サーバーを介したネットワークでは、データの取得がうまくいかないことがあるようです。

APIキーの取得方法

 coneco.netでAPIを使うためには次のような手順でAPIキーを取得して、そのAPIキーを指定してアクセスする必要があります。

 

  1. https://www.coneco.net/api/ にアクセスしてメールアドレスとパスワードを設定
  2. 本登録用URLのお知らせメールに書かれたAPIキー取得用URLをクリック
  3. APIキー発行完了のお知らせメールにある「あなたのAPIキー」をプログラムにセット

商品検索結果の形式

 coneco.netの製品検索結果はJSON形式で取得できます。返されてくるJSON形式に合わせたクラス定義は次のようになります。

リスト2 製品検索結果の定義(ResultContext.vbから抜粋)
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形式のデータを受信します。

リスト3 製品検索結果の定義(ConecoModel.vbから抜粋)
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に割り当てるコードだけが必要です。

リスト4 MainWindow.xaml.vbの内容
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しましょう。

リスト5 MainWindow.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}" />
    </Grid>
</Window>

実行

 この状態でどのような表示になるか実行してみましょう。

図8 Binding後の実行結果
図8 Binding後の実行結果

 正しい結果が表示されているように見えますが、よく見るとタイトルがプロパティ名に変わっていますし、2列目も商品画像の列ではありません。

 これはSPREADのAutoGenerateColumnsプロパティの省略値が、Trueであることと関係しています。このプロパティは、割り当てられたリストの各要素を自動的にSPREADの列に展開してくれる優れものですが、今回のケースではこの機能が働くのは望むべき動きではありません。そこで、AutoGenerateColumnsにFalseを設定して動きを止めたいと思います。

 WindowsフォームではプログラムコードでFalseを設定していたと思いますが、WPFではXAMLで定義するのが良いでしょう。

リスト6 AutoGenerateColumns 設定時のMainWindow.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>

 それでは再度実行してみましょう。

図9 AutoGenerateColumns設定後の実行結果
図9 AutoGenerateColumns設定後の実行結果

 今度は設定したヘッダなども、意図した通りにデータが表示されました。

 とはいえ、ランキングや最低価格、最高価格などは右寄せにしたいですし、製品画像はURLではなく、画像を表示したいところです。次はこの辺りを設定してみましょう。

セル型の設定

 今回の特集では、SPREADに対して徹底的にセルではなく列でさまざまな設定を施します。これはSPREADがセル単位に細かく制御できるという特徴があるため、どうしても公式の情報がセル単位での方法に偏っているためです。

 今手元にあるアプリの状態を再度確認してみましょう。現状は、商品情報サイトからデータを取得し、列ごとにBinding設定をしたSPREADに無事表示できたという地点になります。

 それでは、データの特性に合わせて列の特性を設定しましょう。

SpreadGridデザイナでの作業

 SpreadGridデザイナを起動して、[ランキング]列タイトルをクリックします。[配置]リボングループで、[左寄せ]アイコンをクリックします。同様に[最低価格]列、[最高価格]列についても同じ操作を行います。

図10 イメージ型セルの列全体への設定
図10 イメージ型セルの列全体への設定

 [製品画像]列については、[セル型]リボングループで[イメージ型セル]アイコンをクリックして列全体をイメージ型にします。

実行

 この状態でどのような表示になるか実行してみましょう。

図11 列修飾後の実行結果
図11 列修飾後の実行結果

 左寄せ、画像表示共に意図した表示になっています。

テンプレートデザイナによる複数行表示の設定

 1行での表示がほぼ意図した状態になったところで、いよいよこのデータを1レコード複数行表示に変更してみましょう。

SpreadGridデザイナでの作業

 SpreadGridデザイナの[ツール]リボングループで、[テンプレートデザイナ]アイコンをクリックします。すると今までの表示が[SpreadGrid]ペインと[デザイナ]ペインに分かれて表示されます。[デザイナ]ペインには、先頭4列がサンプルとして1レコード2行2列のフォーマットにデザインされています。このデフォルトでサンプルデザインが表示される仕様は非常に親切な優れものです。

図12 [テンプレートデザイナ]
図12 [テンプレートデザイナ]

 [デザイナ]ペインの最上部には、1レコードの配置デザインに使う設定アイコンが並んでいます。

図13 [テンプレートデザイナ]‐[デザイナ]ペイン
図13 [テンプレートデザイナ]‐[デザイナ]ペイン

 このアイコンの内容からも分かるように、テンプレートの役目はセルの配置に特化しています。よって、列全体も含めセルに関する左寄せなどはテンプレート側ではなく、[SpreadGrid]ペイン側で設定しておく必要があるのです。

 [デザイナ]ペインのセルには右上にマークがついています。このマークが事前に設定済みでまだ割り当てていない列を選択できるマークです。

図14 列インデックスの選択機能
図14 列インデックスの選択機能

 とても単純ですが、[デザイナ]ペインでのデザインを非常に使いやすくしてくれる機能です。

実行

 この状態でどのような表示になるか実行してみましょう。

図15 テンプレートデザイン後の実行結果
図15 テンプレートデザイン後の実行結果

 残念ながらまったく変化がありません。どこが悪いのでしょうか。

 もう一度、SpreadGridデザイナに戻って画面を確認してみると、[デザイナ]ペインのメニューに[テンプレートを使用]というものがあります。

 ためしに[テンプレートを使用]をクリックしたところ、[SpreadGrid]ペインの表示もテンプレートに合わせたものに変化し、また適用して終了したところVisual Studioのウィンドウデザイナでの表示もテンプレートに合わせたものに変わりました。

図16 テンプレートを使用
図16 テンプレートを使用

 この設定を行って実行してみると、1レコード複数行表示が無事完成しました。

図17 テンプレートを使用した実行結果
図17 テンプレートを使用した実行結果

まとめ

 SPREAD for WPF 1.0Jは、今までのSPREAD製品の中でも一番使いやすいSPREAD製品であるように感じます。これはWPFの表現力という点もあるでしょうし、自分のプログラミングノウハウの変化という主観的な面も多く影響していると思えるのですが、SpreadGridデザイナの使い方も含めて、使いたい機能が分かりやすく実装されているというのが初見での感想です。今回実装が見送られた機能を使っていた人には反発も生じるかも知れませんが、機能のスリムアップとそれと(開発リソース的に)バーターであるであろう1レコード複数行表示の導入という大英断には素直に拍手を送りたいと思います。

 カタログスペックレベルで○を多くつけるよりも、一つ一つの○が「これがあってよかった」と何重丸にもしたいくらいの機能が並んでいるコンポーネントを目指してもらいたいと思います。

修正履歴

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/6913 2016/03/14 11:48

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング