SHOEISHA iD

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

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

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

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

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

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

クライアント側の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サービスについて扱っていきます。ご期待ください。

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

  • X ポスト
  • このエントリーをはてなブックマークに追加
Silverlight 2で作成する業務アプリケーション入門連載記事一覧

もっと読む

この記事の著者

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

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

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

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

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

【AD】本記事の内容は記事掲載開始時点のものです 企画・制作 株式会社翔泳社

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

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/3517 2009/01/29 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング