SilverlightアプリケーションからADO.NET Data Servicesでのサービスを呼び出す
では、実際の構築手順に移ります。
前述したサンプルシステムを使用します。開発環境などは前回の記事や上記のサンプルシステムのサイトで確認してください。
ADO.NET Data Servicesの実装は、Silverlightアプリケーションでの活用を考えて、「Silverlight Navigation Application」Visual Studioテンプレートから作成されるWeb側のプロジェクトにします。
まずSilverlightアプリケーションであるMSStoreSample.Clientプロジェクト上で、サービス参照の追加を行います。[探索]ボタンを押下することによって、SilverlightアプリケーションがホストされるプロジェクトMSStoreSample.Webに構築済みのADO.NET Data Servicesの参照が表示されます。名前空間をDataServiceReferenceとして[OK]を押すとプロキシコードが追加されます(ADO.NET Data Servicesの作成は、前回の記事を参照してください)。
これだけの手順でSilverlightアプリケーションからWebサービスの呼び出しに必要なプロキシが作成でき、さらにデータの扱いに対しては、URL操作を意識することなくLINQに代表されるオブジェクト操作で行うことが可能です。
次に画面を構築します。SilverlightアプリケーションであるMSStoreSample.Clientプロジェクト上のHome.xamlに対してListBoxコントロールを追加します。
このプロジェクトはSilverlight Navigation Applicationテンプレートで作成されているため、Home.xamlは、初期表示される画面に相当します。下記にHome.xamlの全リストがあります。今回追加したのは太字の部分です。
<navigation:Page x:Class="MSStoreSample.Client.Home" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation" mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480" Title="Home" Style="{StaticResource PageStyle}"> <Grid x:Name="LayoutRoot"> <StackPanel x:Name="contentStackPanel" Width="600" Margin="0,16,0,0"> <!--カテゴリリスト--> <ListBox x:Name="categoriesList" > <ListBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Name}" TextAlignment="Center" VerticalAlignment="Center" FontWeight="Bold" FontSize="14" > </TextBlock> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </StackPanel> </Grid> </navigation:Page>
最低限の画面ができましたので、今度は実際のデータを取得して、追加したListBoxコントロールを用いてデータを表示したいと思います。Home.xamlのコードビハインド部であるHome.xaml.csに対してコードを記述します。
まず、OnNavigatedToイベントの内部に以下のコードを記載します。このイベントは画面が表示されるタイミングで実行されます。
protected override void OnNavigatedTo(NavigationEventArgs e) { MSStoreSampleEntities context = new MSStoreSampleEntities( new Uri("MSStoreSampleDataService.svc", UriKind.RelativeOrAbsolute)); var categoriesQuery = (from category in context.Categories select category) as DataServiceQuery<Categories>; categoriesQuery.BeginExecute(CategoriesQueryCompleted, categoriesQuery); }
上記のコードにはいくつかポイントがあります。始めにWebサービスのプロキシからデータサービスのインスタンスを作成しています。このときURIオブジェクトを用いてアドレスを指定していますが、前述した同じドメインからのWebサービス呼び出しとなるため、ホストのアドレスは省略しています。
また、データの指定にはLINQ(LINQ to ADO.NET Data Services)を用いています。今回はCotegoriesエンティティを指定しています。
さて、第1回でお話したことですが、SilverligtアプリケーションでのWebサービス呼び出しは必ず非同期実行されます。ここでも、var categoriesQueryと変数を使用していますが、この中にデータの参照があるわけではありません。呼び出しが完了すると、次の行で指定しているCategoriesQueryCompletedが実行されます。まだこの関数は作成していませんので次に表示します。
private void CategoriesQueryCompleted(IAsyncResult result) { Dispatcher.BeginInvoke(() => { DataServiceQuery<Categories> query = result.AsyncState as DataServiceQuery<Categories>; IEnumerable<Categories> categories = query.EndExecute(result).ToList(); categoriesList.ItemsSource = categories; }); }
上記のリストでは、Dispatcher.BeginInvokeでUI側の処理を起こっています。これは、この関数はコールバックであるため、UI制御のスレッドとは別のバックグラウンドで実行されるスレッドとなり、なおかつUIはスレッドセーフではなく、今回のようにUI制御を別スレッドから実行することはできないためです。取得データは最終的に、categoriesList.ItemsSource = categories;
という一文によって、ListBoxのItemsSourceプロパティにセットされます。
では、実行してみましょう。
下記のような画面が表示されるはずです。ListBoxコントロールに対して、ADO.NET Data Servicesから取得されたCotegoriesエンティティ(テーブル)の値が表示されていることが分かります。
サンプルシステムでは、下図のように、リストボックスをタブとして利用するためにリストを横並びに表示して、かつ見た目を変更しています。また、リストを選択すると(タブを選択すると)商品のリストが切り替わるようなコードが実装されています。