SHOEISHA iD

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

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

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

軽量な表形式コンポーネントFlexGridでタッチ対応業務アプリを構築する

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

 グレープシティ社のコンポーネントは、お互いが補完しあいながら一部の機能が重なることによって面として抜けがないように配慮されています。この重なりは重要ですが、同時に「どちらを購入すればよいか?」との迷いが生じる原因でもあります。

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

 例えば、表形式コンポーネントだとSPREADが非常に中心的な存在としてありますが、それと共に人気があるのがFlexGridです。VB6時代に提供されたFlexGridは「SPREADほどの高機能はいらない代わりに少しでも軽いコンポーネントが欲しい」という要望に極めてマッチしたコンポーネントで、バージョンアップにより機能が増えてきましたが、現バージョンでも軽快な動作は失われておらず、特に表形式で参照したいようなときは最初に検討するコンポーネントであることに変わりはありません。

 また、Windowsフォーム、WPF、Windows Runtime(いわゆるモダンUI)の各々をサポートするエディションが提供されている特徴もあります。

FlexGridの今について

 FlexGridは、ComponentOne Studioの一部として入手できます。執筆時点のFlexGridは次のようなエディションがあります。

表1 FlexGrid
  単独製品 ComponentOne Studio
- Enterprise Ultimate
Windowsフォーム - for WinForms
Silverlight - for Silverlight
WPF - for WPF
WinRT - for WinRT XAML

 今回はこの中から、WinFormsWPFWinRTを使って、Microsoft Azure Mobile Servicesに保存されているデータを取得し一覧表示を行うサンプルを作成して、それぞれの使い勝手を検証したいと思います。

 Microsoft Azure Mobile Service側は、AED検索オープンデータとして公開されているものを使います。AED検索オープンデータの詳細は「AED検索サポートページ」を参照してください。

 なお、AED検索オープンデータは、Microsoft Azure Mobile Servicesで動作しているのでMobile Service SDKを使ってアクセスしてもいいのですが、https-GETでデータをリクエストするとJSON形式のデータが返信されてくる、いわゆるREST/JSONインターフェースを採用しているので、SDKを使わずに利用してみたいと思います。

エディション間で共通の作業

 今回、3つのエディションでサンプルを作成しますが、ロジック部分はほぼ共通的な構造になっています。以下の、NuGetパッケージ追加、プロジェクト構造、ロジック記述は、各サンプル用の新規プロジェクト作成直後に同じように実施する項目になります。

NuGetパッケージ追加

 REST/JSONを扱う場合、NuGetから「Json.NET」と「Microsoft HTTP Client Libraries」のNuGetパッケージを追加しておくと便利です。

図1 NuGetパッケージの追加
図1 NuGetパッケージの追加

プロジェクト構成

 今回のサンプルでは、見た目とロジックを分離してその間をBindingという疎結合で結びつける方式に対応しているので、プロジェクト構成もModel-ViewModel-Viewとして、Modelにロジック、Viewに見た目を記載します。WPF版のサンプルプロジェクト構造は次のようになります。

図2 プロジェクト構成
図2 プロジェクト構成

ロジック記述

 AED位置情報を取得するモデルであるAEDModelには、次のコードを記載します。

リスト1 AEDModel.vb
Imports System.Collections.ObjectModel
Imports System.ComponentModel
Imports System.Runtime.CompilerServices
Imports System.Net.Http
Imports Newtonsoft.Json

Namespace Models
    Public Class AedInfo
        Public Property Id As Long
        Public Property LocationName As String
        Public Property Perfecture As String
        Public Property City As String
        Public Property AddressArea As String
        Public Property Latitude As Single
        Public Property Longitude As Single
        Public Property FacilityPlace As String
        Public Property ScheduleDayType As String
        Public Property PhotoOfAedUrl As String
        Public Property FacilityNote As String
    End Class

    Public Class AedModel
        Implements INotifyPropertyChanged

        Public Property Items As New ObservableCollection(Of AedInfo)

        Private Const AppUrl As String = "https://aed.azure-mobile.net/api/aedinfo/{0}/{1}"

        Public Async Function SelectData() As Task
            Try
                Dim url As String = String.Format(AppUrl, "神奈川県", "鎌倉市")
                Dim client = New HttpClient()
                Dim jsonString = Await client.GetStringAsync(New Uri(url))
                Dim json = JsonConvert.DeserializeObject(Of IEnumerable(Of AedInfo))(jsonString)

                Me.Items.Clear()
                For Each item In json
                    Me.Items.Add(item)
                Next
            Catch ex As Exception
                Debug.Assert(ex.Message)
            End Try
        End Function

        Public Event PropertyChanged(sender As Object,
                                     e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
        Protected Sub OnPropertyChanged(<CallerMemberName> Optional propertyName As String = Nothing)
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
        End Sub
    End Class
End Namespace

 今回のサンプルでは、SelectDataメソッドを実行すると、Itemsプロパティに取得した神奈川県鎌倉市のAED位置情報が設定されてきます。

FlexGrid for WPF

 共通作業が終わったので、FlexGrid for WPFのサンプルに必要な作業を開始します。

FlexGridの設置

 ツールボックスに「WPFコンポーネント」からC1FlexGridを追加し、さらにメインフォームにドラッグ&ドロップで設置します。

リスト2 MainWindow.xaml
<Window
    x:Class="Views.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:c1="http://schemas.componentone.com/winfx/2006/xaml" 
    Title="MainWindow" Height="300" Width="300">
    <Grid>

        <c1:C1FlexGrid HorizontalAlignment="Left" VerticalAlignment="Top"
                       ItemsSource="{Binding Items}"
                       Margin="10" 
                       IsReadOnly="True"
                       AutoGenerateColumns="True" >
        </c1:C1FlexGrid>
    </Grid>
</Window>

 ItemSourceプロパティにBinding設定を忘れずに指定しましょう。

Binding設定

 MainWindow.xamlのコードビハインド側に、ロジックからのItemsをBindingするコードを追記します。直接AEDModel.vbを使うのではなく、間にMainViewModelクラスをはさんでいる点に注意してください。MainViewModelクラスは、Application.vbでMainVM変数にインスタンシング化して格納されています。

リスト3 MainWindow.xaml.vb
Namespace Views
    Public Class MainWindow
        Public Sub New()
            InitializeComponent()
            Me.DataContext = Application.MainVM
            SelectData()
        End Sub

        Private Async Sub SelectData()
            Await Application.MainVM.SelectData()
        End Sub
    End Class
End Namespace

 MainWindowクラスがnewされると、DataContextにMainViewModelクラスのインスタンスを設定し、それからSelectDataメソッドを呼び出します。SelectDataメソッドで値が設定されるItemsプロパティの内容は、MainWindow.xamlで指定してあるようにFlexGridにBindingされているので、Itemsプロパティの内容が変化すれば即座にFlexGridの表示に反映されます。

実行

 FlexGridには、最小の手順で結果を得られるようにAutoGenerateColumnsという機能があり、AutoGenerateColumnsプロパティをTrueにすることで、Bindingしたプロパティ構造を自動的に列に展開する機能があります。

図3 AutoGenerateColumns の実行結果
図3 AutoGenerateColumns の実行結果

 そのため、事前に定義をしなくても一覧表示が可能です。

表示列の明示的指定

 AutoGenerateColumns機能を使うと不要な列を非表示にしたり、列の順番の初期位置を変更したりできません。そのような要望がある場合は、明示的に列と列に表示するプロパティ値を指定します。

リスト4 MainWindow.xaml
<Window
    x:Class="Views.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:c1="http://schemas.componentone.com/winfx/2006/xaml" 
    Title="{Binding Items[0].Perfecture}" Height="300" Width="300">
    <Grid>

        <c1:C1FlexGrid HorizontalAlignment="Left" VerticalAlignment="Top"
                       ItemsSource="{Binding Items}"
                       Margin="10" 
                       IsReadOnly="True"
                       AutoGenerateColumns="False" >
            <c1:C1FlexGrid.Columns>
                <c1:Column Header="設備写真">
                    <c1:Column.CellTemplate>
                        <DataTemplate>
                            <Image Source="{Binding PhotoOfAedUrl}" />
                        </DataTemplate>
                    </c1:Column.CellTemplate>
                </c1:Column>
                <c1:Column Binding="{Binding LocationName}" Header="施設名" Width="150" />
                <c1:Column Binding="{Binding City}" Header="市町村区" Width="50" />
                <c1:Column Binding="{Binding AddressArea}" Header="住所" Width="150" />
                <c1:Column Binding="{Binding Latitude}" Header="緯度" />
                <c1:Column Binding="{Binding Longitude}" Header="経度" />
            </c1:C1FlexGrid.Columns>
        </c1:C1FlexGrid>
    </Grid>
</Window>

 <c1:C1FlexGrid.Columns>タグの中に必要な列の<c1:Column>タグを定義してあります。忘れてはいけないのは、AutoGenerateColumnsプロパティをFalseにすることです。

 今回は、設備写真の画像URLをImageとして表示するように列属性の変更も行っています。

実行

図4 列指定後の実行結果
図4 列指定後の実行結果

 かなり最適化された一覧表示ができあがりました。

FlexGrid for WinRT XAML

 WPF版に引き続き、同様にFlexGrid+XAMLという形式で画面が定義できるWindowsストアアプリでの使い方も確認してみましょう。

NuGetパッケージ追加

 Windowsストアアプリのプロジェクトでも「Json.NET」と「Microsoft HTTP Client Libraries」のNuGetパッケージが存在します。

図5 NuGetパッケージの追加
図5 NuGetパッケージの追加

プロジェクト構成

 Windowsストアアプリ版のサンプルプロジェクト構造は次のようになります。

図6 プロジェクト構成
図6 プロジェクト構成

 AEDModel.vbとMainViewModel.vbはWPF版がそのまま使えるので、既存項目の追加で所定のフォルダに追加します。

FlexGridの設置

 ツールボックスに「WindowsおよびWindows Phone XAMLコンポーネント」からC1FlexGridを追加し、さらにメインフォームにドラッグ&ドロップで設置します。

リスト5 MainPage.xaml(抜粋)
    :
 (中略)
    :
        <Grid Grid.Row="1">
            <c1:C1FlexGrid HorizontalAlignment="Left" VerticalAlignment="Top"
                           ItemsSource="{Binding Items}"
                           Margin="10"
                           IsReadOnly="True"
                           AutoGenerateColumns="True" >
            </c1:C1FlexGrid>
        </Grid>
    :
 (中略)
    :

Binding設定

 MainPage.xamlのコードビハインド側に、ロジックからのItemsをBindingするコードを追記します。

リスト6 MainPage.xaml.vb(抜粋)
    :
 (中略)
    :
        Public Sub New()
            InitializeComponent()
            Me._navigationHelper = New Common.NavigationHelper(Me)
            AddHandler Me._navigationHelper.LoadState, AddressOf NavigationHelper_LoadState
            AddHandler Me._navigationHelper.SaveState, AddressOf NavigationHelper_SaveState
            Me.DataContext = App.MainVM
            SelectData()
        End Sub

        Private Async Sub SelectData()
            Await App.MainVM.SelectData()
        End Sub
    :
 (中略)
    :

 MainPageクラスがnewされると、DataContextにMainViewModelクラスのインスタンスを設定し、それからSelectDataメソッドを呼び出します。SelectDataメソッドで値が設定されるItemsプロパティの内容は、MainPage.xamlで指定してあるようにFlexGridにBindingされているので、Itemsプロパティの内容が変化すれば即座にFlexGridの表示に反映されます。

実行

 Windowsストアアプリ版でもAutoGenerateColumnsという機能があります。

図7 AutoGenerateColumns の実行結果
図7 AutoGenerateColumns の実行結果

 そのため、事前に定義をしなくても一覧表示が可能です。

表示列の明示的指定

 もちろんAutoGenerateColumns機能を使わずに列指定で一覧表示することも可能です。

リスト7 MainPage.xaml(抜粋)
    :
 (中略)
    :
<c1:C1FlexGrid HorizontalAlignment="Left" VerticalAlignment="Top"
                ItemsSource="{Binding Items}"
                Margin="10"
                IsReadOnly="True"
                AutoGenerateColumns="False" >
    <c1:C1FlexGrid.Columns>
        <c1:Column Header="設備写真">
            <c1:Column.CellTemplate>
                <DataTemplate>
                    <Image Source="{Binding PhotoOfAedUrl}" />
                </DataTemplate>
            </c1:Column.CellTemplate>
        </c1:Column>
        <c1:Column Binding="{Binding LocationName}" Header="施設名" Width="300" />
        <c1:Column Binding="{Binding City}" Header="市町村区" Width="100" />
        <c1:Column Binding="{Binding AddressArea}" Header="住所" Width="300" />
        <c1:Column Binding="{Binding Latitude}" Header="緯度" />
        <c1:Column Binding="{Binding Longitude}" Header="経度" />
    </c1:C1FlexGrid.Columns>
</c1:C1FlexGrid>
    :
 (中略)
    :

 <c1:C1FlexGrid.Columns>タグの中に必要な列の<c1:Column>タグを定義してあります。忘れてはいけないのは、AutoGenerateColumnsプロパティをFalseにすることです。

 今回は、設備写真の画像URLをImageとして表示するように列属性の変更も行っています。

実行

図8 列指定後の実行結果
図8 列指定後の実行結果

FlexGrid for WinForms

 最後にXAMLではなくWindowsフォームでのFlexGridの使い勝手を確認してみましょう。

NuGetパッケージ追加

 Windowsフォームのプロジェクトでも「Json.NET」と「Microsoft HTTP Client Libraries」のNuGetパッケージが存在します。

図9 NuGetパッケージの追加
図9 NuGetパッケージの追加

プロジェクト構成

 WindowsフォームでもBindingが利用可能なので、プロジェクト構成もModel-ViewModel-Viewとして、Modelにロジック、Viewに見た目を記載します。

図10 プロジェクト構成
図10 プロジェクト構成

 AEDModel.vbとMainViewModel.vbはWPF版がそのまま使えるので、既存項目の追加で所定のフォルダに追加します。

FlexGridの設置

 ツールボックスに「.NET Frameworkコンポーネント」からC1FlexGridを追加し、さらにメインフォームにドラッグ&ドロップで設置します。

 FlexGridのデータソースとしてMainViewModelクラスを指定します。

図11 データソースにオブジェクトを指定
図11 データソースにオブジェクトを指定

 これでBindingの指定も完了です。

Binding設定

 MainForm.vbのコードビハインド側で、SelectDataメソッドを呼び出してItemsをDataSourceに指定するコードを追記します。

リスト8 MainForm.vb
Imports CZ1407Win.ViewModels

Public Class MainForm
    Private MainVM As New MainViewModel

    Public Sub New()
        InitializeComponent()
        SelectData()
    End Sub

    Private Async Sub SelectData()
        Await Me.MainVM.SelectData()
        Me.MainViewModelBindingSource.DataSource = Me.MainVM.Items
    End Sub
End Class

実行

 デフォルト状態ではAutoGenerateColumnsがTrueなので、このまま実行してみます。

図12 AutoGenerateColumns の実行結果
図12 AutoGenerateColumns の実行結果

表示列の明示的指定

 列を明示的に指定するときは列エディタを使用します。

図13 列エディタ
図13 列エディタ

実行

図14 列指定後の実行結果
図14 列指定後の実行結果

 設備変更欄に画像を表示するためには、コードビハインド側で明示的に画像URLから画像データに変換するなどの処理が必要になるため、今回は確認を省略したいと思います。

まとめ

 FlexGridを使ってWebサービスから取得した値を一覧表示してみましたが、いかががだったでしょうか。AutoGenerateColumnsなどを活用して素早く手軽に一覧表示ができるのは使っていてかなり気持ちが良かったです。これからはSPREADだけではなくFlexGridについても評価の対象にしていきたいと思いました。

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

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

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

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/7957 2014/11/07 15:25

イベント

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング