CodeZine(コードジン)

特集ページ一覧

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

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

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

クライアント側のXAML修正・データバインド処理

 続いてPage.xamlの編集です。Expression Blendでコントロールを追加しましょう。以下に編集中の画面を示します。

Page.xamlを編集
Page.xamlを編集

 XAMLは次のようになります。

Page.xamlの内容(太字部分はバインディングに関する記述 {Binding…}構文はVisual Studioで追記)
<ComboBox Height="24" Width="112" x:Name="comboBox1" ItemsSource="{Binding}"  DisplayMemberPath="Name" SelectionChanged="comboBox1_SelectionChanged" Grid.Row="1" d:LayoutOverrides="Width, Height" VerticalAlignment="Bottom" HorizontalAlignment="Left" Margin="126.364,0,0,225"/>
<StackPanel Height="79" Margin="126,0,0,120" VerticalAlignment="Bottom" Grid.Row="1" x:Name="stackPanel1" Orientation="Vertical" Width="274" HorizontalAlignment="Left" >
    <StackPanel Height="23" Width="Auto" Orientation="Horizontal" x:Name="stackPanel2">
        <TextBlock  Text="{Binding Path=Work}" TextWrapping="Wrap" Width="70" Height="Auto" Margin="11,0,30,0" x:Name="textBlock6"/>
        <CheckBox IsChecked="{Binding Path=Check}" IsEnabled="False" Height="Auto" Width="Auto" Margin="20,0,0,0" Content="チェック" x:Name="checkBox1" />
    </StackPanel>
    <TextBox Height="Auto" Width="Auto" x:Name="textBox1" Text="{Binding Path=Ref}" TextWrapping="Wrap" RenderTransformOrigin="0.5,1.667" Margin="10,20,0,0"/>
</StackPanel>
<TextBlock x:Name="textBlock1" Height="Auto" Margin="232.364,0,375.636,84" VerticalAlignment="Bottom" Grid.Row="1" TextWrapping="Wrap" ><Run Text="に変更します。"/><LineBreak/><Run Text="よろしければ更新を押してください"/></TextBlock>
<TextBlock Height="Auto" HorizontalAlignment="Left" Margin="99.272,0,0,230" VerticalAlignment="Bottom" Width="Auto" Grid.Row="1" Text="名前" TextWrapping="Wrap" x:Name="textBlock4"/>
<TextBlock Height="Auto" HorizontalAlignment="Left" Margin="100,0,0,136" VerticalAlignment="Bottom" Width="Auto" Grid.Row="1" Text="内容" TextWrapping="Wrap" x:Name="textBlock2" RenderTransformOrigin="0.545,-0.5"/>
<TextBlock Height="Auto" HorizontalAlignment="Left" Margin="99.636,0,0,183" VerticalAlignment="Bottom" Width="Auto" Text="所属" TextWrapping="Wrap" x:Name="textBlock3" RenderTransformOrigin="0.545,-0.5" Grid.Row="1"/>
<TextBlock Height="Auto" HorizontalAlignment="Left" Margin="15.728,0,0,230" VerticalAlignment="Bottom" Width="Auto" Text="予定の編集" TextWrapping="Wrap" x:Name="textBlock5" Grid.Row="1"/>

 いろいろなコントロールを配置していますが、重要なのは太字でも示した、

  • 顧客を選択するためのComboBox
  • データバインドをまとめて行うためのStackPanel(2つStackPanelがありますが、stackPanel2は単なるレイアウト用で、重要なのは1つ目のstackPanel1です)
  • stackPanel1以下に配置したTextBlock・CheckBox・TextBox

 です。

  他にもいくつかTextBlockを配置していますが、これらは単純なテキスト表示のためのコントロールでデータバインディングとは関係ありません。また、レイアウトは今回の本論とはあまり関係ありませんので、詳細は上記キャプチャ画面を参考にして設定してください。

 さて、バインド関係の記述はVisual Studioに戻ってから行います。以下に設定した主なプロパティ一覧を示します。

設定した主要なプロパティ
コントロール名 プロパティ 概要
comboBox1 ItemsSource="{Binding}" ページ全体のDataContextを利用
DisplayMemberPath="Name" コンボボックスで表示するプロパティを指定
SelectionChanged="comboBox1_SelectionChanged" イベントハンドラ
textBlock6 Text="{Binding Path=Work}" DataContextで指定されるオブジェクトのWorkプロパティの値を表示(Visual Studioで追記)
textBox1 Text="{Binding Path=Ref}" DataContextで指定されるオブジェクトのRefプロパティの値を表示(Visual Studioで追記)
checkBox1 IsChecked="{Binding Path=Check}" DataContextで指定されるオブジェクトのCheckプロパティの値(bool値)を表示(Visual Studioで追記)

 続いて、Page.xamlのビハインドコードPage.xaml.csに変更を加えます。以下に追記したコードを示します。

Page.xaml.csの内容(コンボボックス選択によるデータバインド部分)
using System.Windows.Browser; //追加したディレクティブ

public void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)//comboBox1の選択変更時に呼び出されるイベント
{
  if (comboBox1.SelectedItem != null)
    {
      Customer comboData = (Customer)comboBox1.SelectedItem;//選択されたアイテムを取得
      stackPanel1.DataContext = comboData;
      //StackPanel内のDataContextを設定→その下のコントロールにも反映される
    }
}

 comboBox1の選択でイベントが発生し、XAML側で設定したとおり、comboBox1_SelectionChangedメソッドが呼び出されます。ここで、comboBoxで選択した顧客データ(Customerオブジェクト)がstackPanel1のDataContextに設定されます。これによりstackPanel1以下のコントロールのバインド元が設定され、textBox1、TextBlock6、checkBox1にそれぞれ選択した顧客のデータがバインドされます。

 この時点でユーザーコントロール全体には、サンプル1で実装したとおり、顧客リスト全体(Customerクラスのリスト)がバインドされており、画面上のDataGridは顧客リスト全部を表示しています。一方で、stackPanel1のDataContextはcomboBox1で選択した顧客1人を表すCustomerクラスが設定されており、stackPanel1以下のコントロールは、この顧客の情報のみを表示しています。1つの画面上で、異なるオブジェクトがバインドされていることに注目してください。

Webサービスへのデータ送信

 最後に、更新したデータをWebサーバに送りましょう。サンプル1で記述した、更新ボタンのイベントハンドラを次のように変更します。

Page.xaml.csの内容(データ更新部分)
private void Button_Click(object sender, RoutedEventArgs e)
{
  if (comboBox1.SelectedItem != null)
    {
      Customer comboData = (Customer)comboBox1.SelectedItem;//選択されたアイテムを取得
      comboData.Ref = textBox1.Text;//選択されているIDのRefプロパティに入力内容を代入
      SetItem(comboData);//内容を引数にメソッドを呼び出す
    }
}
public void SetItem(Customer comboData) //サーバへのデータ送信メソッド

{
  string id = comboData.ID;//IDを取得
  string re = comboData.Ref;//変更されたRefを取得
  var webclient = new WebClient();
  webclient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(customer_ChangeStringCompleted);
  webclient.DownloadStringAsync(new Uri(string.Format("http://localhost:8080/UpdateCustomerRef.aspx?data1={0}&data2={1}", HttpUtility.UrlEncode(id), HttpUtility.UrlEncode(re))));//変更内容をURLに乗せてWebサービスを呼び出す

}
public void customer_ChangeStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{ //HTTPリクエスト完了後のイベントハンドラ
  ReadContent(); //データを再読込する
}

 textBox1に変更内容を入力し、更新ボタンを押下すると選択されているComboBoxのID値とテキストボックスに入力したテキストがSetItemメソッドに渡されます。さらにそれらのデータはURL上に乗せられて、XML更新用のサイトに渡されます。

 サーバでの処理完了後、クライアント側のイベントハンドラでリスト再読込が実行されます。

 では実行してみましょう。顧客リストがDataGridにバインドされるところまではサンプル1と同様ですが、下のコンボボックスに顧客一覧がバインドされています。コンボボックスで顧客名を選択すると、各顧客の所属企業、チェックボックスの内容、予定欄の内容が表示されます。予定を書き換え、更新ボタンを押すとサーバ側に値が渡されてデータが更新されます。DataGrid上の表示も変化し、実際のXMLファイルも書き換わっているはずです。

OneTime or OneWay or TwoWay?

 今回のサンプルはデータバインディングのバインドモードとして、OneTimeモードのみを使用しています。

 OneWayモードを使えば、最後のデータ更新をサーバに投げた後、再読込することなく、元のDataGridの予定欄の表示を更新させることができます。また、TwoWayモードを使うと、テキストボックスを更新した地点で、書き換えた内容がオブジェクトに反映されるため、イベントハンドラで明示的にテキストボックスの内容をオブジェクトに書き戻す必要が無くなります。なお、OneWay / TwoWayモードを使うには、バインド元オブジェクトであるCustomerクラスにINotifyPropertyChangedインターフェイスを実装する必要があります。

 Silverlightのようなリッチクライアント環境では、データがローカルにあるのではなく、サーバ側に存在することも多いため、TwoWayモードよりもOneTime / OneWayモードでの実装が自然な場合も多いでしょう。

まとめ

 今回は、サーバとXMLデータをやり取りするというモデルを使ってデータバインディングを体験しました。Silverlighでオブジェクトとコントロールのプロパティの連係を簡単に実現できることが実感できたかと思います。最終回の次回はWebサービスについて扱っていきます。ご期待ください。



  • 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