CodeZine(コードジン)

特集ページ一覧

Silverlight 2でのデータバインディング

Silverlight 2で作成する業務アプリケーション入門(5)

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2009/01/29 14:00
目次

クライアント側実装 DataGridコントロールの自動列生成のテスト

 続いてクライアント側実装に移りましょう。Page.xamlをExpression Blendで編集します。デフォルトでは参照情報が足りないためDataGridコントロールが利用できません。Expression BlendでDataGridを利用するため、Visual Studio側で参照情報を設定しておきます。Visual Studioのソリューションエクスプローラで[参照設定]を右クリックし[参照の追加]でSystem.Windows.Controls.Dataを追加しておきましょう。これでDataGridコントロールが有効になります。また、DataGridコントロールとは関係ありませんが、後で使用するので、ついでにSystem.Xml.Linqの参照も追加しておきます。

 編集時の画面は次のとおりです。

Expression BlendでPage.xamlを編集
Expression BlendでPage.xamlを編集

 上段グリッドにTextBlockを配置し下段グリッドにはアセットライブラリからDataGridとButtonをドロップします。それぞれマウスで適当な位置に配置し、大きさなどのスタイルを整えます。

アセットライブラリからDataGridを追加
アセットライブラリからDataGridを追加

 DataGridに設定するプロパティですが、AutoGenerateColumnsプロパティにTrueを設定しました。これはバインドするデータによって自動的に列を生成する機能です。まずはこの機能を利用してDataGridの基本的な動作を試してみましょう。

 バインドに関する設定を行うには、プロパティウィンドウからItemSourceのボックスをクリックします。以下の画面が出現します。

ItemsSourceを設定
ItemsSourceを設定

 メニューから[カスタム式]を選択します。ここに「{Binding}」とだけ入力します。今回、データソースを指定するDataContextプロパティはビハインドコードで設定しますのでPage.xaml側に記述するのはこれだけで十分です。

 さらにUserControlには読み込み時に発生するLoadedイベントのハンドラを設定しました。

 以下に設定した主なプロパティの一覧を示します。

主なプロパティ(レイアウト関連のプロパティなどは省略)
コントロール名 プロパティ 概要
UserControl Loadedイベント ユーザーコントロール読み込み時に発生するイベントのハンドラ。WebサービスからXML形式の顧客リストを読み込む機能を実装する
DataGrid AutoGenerateColumns 読み込んだデータに応じて列を自動的に生成するプロパティ
ItemsSource バインド情報を設定
IsReadOnly 読み取り専用の属性を設定
Button Clickイベント ページ更新のハンドラ

 実際のXAMLコードは次のとおりです。

Page.xaml
<UserControl xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"  x:Class="DataBindApplication1.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="800" Height="600" Loaded="UserControl_Loaded" xmlns:DataBindApplication1="clr-namespace:DataBindApplication1" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
    <Grid x:Name="LayoutRoot" Background="White">
      <Grid.RowDefinitions>
        <RowDefinition Height="0.133*"/>
        <RowDefinition Height="0.867*"/>
      </Grid.RowDefinitions>
      <TextBlock HorizontalAlignment="Left" Margin="48,24,0,32" Width="Auto" Text="顧客リスト" TextWrapping="Wrap" FontSize="16"/>
      <data:DataGrid Margin="48,48,248,192" Grid.Row="1" x:Name="list1" AutoGenerateColumns="True" ItemsSource="{Binding}" IsReadOnly="False" />
      <Button HorizontalAlignment="Right" Margin="0,0,248,154" VerticalAlignment="Bottom" Grid.Row="1" Content="更新" Click="Button_Click" RenderTransformOrigin="0.429,-1.182" Width="48"/>
    </Grid>
</UserControl>

 続いて、XMLの顧客リストの各要素をプロパティに持つCustomerクラスを定義します。実際のデータバインドは、このCustomerクラスのリストをバインド元オブジェクトにすることになります。ソリューションエクスプローラのクライアント側[DataBindApplication1]で右クリックし[追加]-[新しい項目]-[クラス]でCustomer.csを作成します。以下にコードを示します。

Customer.cs
namespace DataBindApplication1
{
    public class Customer
    {
        public string ID { get; set; }
        public string Name { get; set; }
        public string Work { get; set; }
        public string Mail { get; set; }
        public bool Check { get; set; }
        public string Ref { get; set; }
    }
}

 ちなみに、プロパティの定義に利用したのはC# 3.0からの機能である自動プロパティです。これはプロパティの実体となる変数を定義することなくプロパティを使用できる便利機能です。

 Customerクラスは前述の顧客リストXMLのItem要素に対応し、Item要素以下の子要素に対応するプロパティを持ちます。後述するように、サーバから取得したXMLをLINQでこのCustomerクラスに変換し、データソースとします。

 最後にPage.xamlのビハインドコード、Page.xaml.csを作成します。

Page.xaml.cs
using System.Xml.Linq;  //usingディレクティブを追加
...中略...

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
  ReadContent();  //ユーザーコントロールがロードされた時にデータを読み込む
}
public void customer_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{ //Webサービスからのデータ取得が終わった時の処理
  XDocument Xmllist = XDocument.Parse(e.Result); //取得した文字列をXML文書にして代入
  var customers = from customer in Xmllist.Descendants("Item")
    select new Customer         //LINQを使ってXMLの各要素を新しいCustomerオブジェクトとして出力
      {
        ID = (string)customer.Element("ID"),
        Name = (string)customer.Element("Name"),
        Work = (string)customer.Element("Work"),
        Mail = (string)customer.Element("Mail"),
        Check = (bool)customer.Element("Check"),
        Ref = (string)customer.Element("Ref")

        };
  this.DataContext = customers ; //ユーザーコントロール全体に適用されるDataContextを設定
}
public void ReadContent()   //ページロードおよび更新ボタン共通のイベント
{
  WebClient customer = new WebClient();   //HTTPリクエストを行うクラス
  customer.DownloadStringCompleted += new DownloadStringCompletedEventHandler(customer_DownloadStringCompleted);
  //ダウンロード完了時のイベントハンドラを設定
  customer.DownloadStringAsync(new Uri("http://localhost:8080/Default.aspx")); //非同期的にサーバ側に作成したサービスにアクセス
}
private void Button_Click(object sender, RoutedEventArgs e)
{
  ReadContent();  //更新ボタンが押された際にもデータを読み込む
}

 まず、LINQを使うのでusingディレクティブに「System.Xml.Linq;」を追加します。LINQに関しては本論から離れるので詳述しませんが、

from (クエリの中でのみ有効な一時変数)in (データソース)select (出力形式)

 という形式で記述しています。ここでは取得したXMLのItem要素を順にcustomerという変数に取り出し、各要素をプロパティに変換しながらCustomerクラスに変換し、Customerクラスの集合をcustomers変数に代入しています。LINQについては連載第4回も併せて参照してください。

  他の各部の動作についてはコメントを参照いただくとして、ここではバインディングに関連する部分に注目してみます。

DataContextの設定
this.DataContext = customers;

 この記述でユーザーコントロール全体のバインド元オブジェクトとして、customers変数が設定されます。この結果XAMLファイル内で特にソースを明示せずデータバインディングを実行した場合、ここで設定したDataContextが継承されます。

 では、ここまででとりあえず実行してみましょう。

列が自動生成されたDataGrid
列が自動生成されたDataGrid

 サーバ上のXMLデータをダウンロードし、Customerクラスのオブジェクトに変換したものを、DataGridにバインドして表示しています。boolean型の変数は自動的にCheckBoxで、それ以外の要素はTextBoxで表示されています。

 試しにXMLファイルを開いて適当な要素を改変したうえで更新ボタンを押下してください。表示される値が変更されるのを確認できるでしょう。


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

バックナンバー

連載:Silverlight 2で作成する業務アプリケーション入門

著者プロフィール

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XM...

  • WINGSプロジェクト 土井 毅(ドイ ツヨシ)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂...

あなたにオススメ

All contents copyright © 2005-2022 Shoeisha Co., Ltd. All rights reserved. ver.1.5