ここで、お小遣いService.csの中身を軽く見ておきましょう。
リスト1は、自動生成されたコードからコメントを取り除いたものです。
図13でドメインサービスを作成したときに、お小遣い明細、お小遣い分類に対する検索処理、お小遣い明細に対する追加/更新/削除の処理が、指定通りにドメインサービスに追加されていることが確認できます。
ここでは、日付のFrom/Toから明細を検索する「Findお小遣い明細ByDate」メソッドを、新たに追加しています。
注意が必要なのは、WCF RIA Serviceで公開するメソッドはオーバーロード(引数が違う同名のメソッドを定義)することはできない点です。例えば、お小遣い帳のデータをすべて取得する「IQueryable Getお小遣い明細()」メソッドと、検索条件を指定して取得する「IQueryable Getお小遣い帳(DateTime, DateTime)」は、同時に1つのサービスに設定できません。この場合は、値を取得するメソッドを「Find~~ByDate」のように、別名でメソッドを追加する必要があります。
namespace RIAServicesSample.Web { using System; using System.Data; using System.Linq; using System.ServiceModel.DomainServices.EntityFramework; using System.ServiceModel.DomainServices.Hosting; [EnableClientAccess()] public class お小遣いService : LinqToEntitiesDomainService<お小遣いEntities> { public IQueryable<お小遣い分類> Getお小遣い分類() { return this.ObjectContext.お小遣い分類; } public IQueryable<お小遣い明細> Getお小遣い明細() { return this.ObjectContext.お小遣い明細; } // 新たに手動で追加した検索メソッド public IQueryable<お小遣い明細> Findお小遣い明細ByDate(DateTime from, DateTime to) { return this.ObjectContext.お小遣い明細.Where(明細 => from <= 明細.日付 && 明細.日付 >= to); } public void Insertお小遣い明細(お小遣い明細 お小遣い明細) { if ((お小遣い明細.EntityState != EntityState.Detached)) { this.ObjectContext.ObjectStateManager.ChangeObjectState(お小遣い明細, EntityState.Added); } else { this.ObjectContext.お小遣い明細.AddObject(お小遣い明細); } } public void Updateお小遣い明細(お小遣い明細 currentお小遣い明細) { this.ObjectContext.お小遣い明細.AttachAsModified(currentお小遣い明細, this.ChangeSet.GetOriginal(currentお小遣い明細)); } public void Deleteお小遣い明細(お小遣い明細 お小遣い明細) { if ((お小遣い明細.EntityState == EntityState.Detached)) { this.ObjectContext.お小遣い明細.Attach(お小遣い明細); } this.ObjectContext.お小遣い明細.DeleteObject(お小遣い明細); } } }
以上で、サーバ側のサービスの準備は終わりです。
データの表示
サーバ側のドメインサービスが用意できたので、Silverlightでデータを取得してDataGridに一覧表示してみましょう。Silverlight側のプロジェクトのMainPage.xamlを開き、データソースウインドウからお小遣い明細をページにドロップします(図14)。
図14で自動生成されたXAMLに対して、リストに表示する必要のない最終更新日などのプロパティを除き、レイアウトを修正したコードがリスト2です。
検索フィールドに配置されたLoadボタンは、「お小遣い明細DomainDataSource」クラスのLoadCommandメソッドにバインドされています。
<UserControl x:Class="RIAServicesSample.MainPage" 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" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400" xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.DomainServices" xmlns:my="clr-namespace:RIAServicesSample.Web" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"> <StackPanel x:Name="LayoutRoot" Background="White"> <!-- データソースの定義 --> <riaControls:DomainDataSource AutoLoad="False" d:DesignData="{d:DesignInstance my:お小遣い明細, CreateList=true}" LoadedData="お小遣い明細DomainDataSource_LoadedData" Name="お小遣い明細DomainDataSource" QueryName="Findお小遣い明細ByDateQuery"> <riaControls:DomainDataSource.DomainContext> <my:お小遣いContext /> </riaControls:DomainDataSource.DomainContext> <riaControls:DomainDataSource.QueryParameters> <riaControls:Parameter ParameterName="from" Value="{Binding ElementName=fromTextBox, Path=Text}" /> <riaControls:Parameter ParameterName="to" Value="{Binding ElementName=toTextBox, Path=Text}" /> </riaControls:DomainDataSource.QueryParameters> </riaControls:DomainDataSource> <!-- 検索フィールド --> <StackPanel Orientation="Horizontal" > <sdk:Label Content="From:" VerticalAlignment="Center" /> <sdk:DatePicker Name="fromTextBox" Width="120" /> <sdk:Label Content="To:" VerticalAlignment="Center" /> <sdk:DatePicker Name="toTextBox" Width="120" /> <Button Command="{Binding Path=LoadCommand, ElementName=お小遣い明細DomainDataSource}" Content="検索" Name="お小遣い明細DomainDataSourceLoadButton" /> </StackPanel> <!-- データグリッド --> <sdk:DataGrid AutoGenerateColumns="False" Height="200" Width="400" HorizontalAlignment="Left" ItemsSource="{Binding ElementName=お小遣い明細DomainDataSource, Path=Data}" Name="お小遣い明細DataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" VerticalAlignment="Top"> <sdk:DataGrid.Columns> <sdk:DataGridTemplateColumn Header="日付" Width="SizeToHeader"> <sdk:DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <sdk:DatePicker SelectedDate="{Binding Path=日付, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" /> </DataTemplate> </sdk:DataGridTemplateColumn.CellEditingTemplate> <sdk:DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding Path=日付, StringFormat=\{0:d\}}" /> </DataTemplate> </sdk:DataGridTemplateColumn.CellTemplate> </sdk:DataGridTemplateColumn> <sdk:DataGridTextColumn Binding="{Binding Path=連番}" Header="連番" Width="SizeToHeader" /> <sdk:DataGridTextColumn Binding="{Binding Path=お小遣い分類Id}" Header="お小遣い分類" Width="SizeToHeader" /> <sdk:DataGridTextColumn Binding="{Binding Path=タイトル}" Header="タイトル" Width="SizeToHeader" /> <sdk:DataGridTextColumn Binding="{Binding Path=金額}" Header="金額" Width="SizeToHeader" /> </sdk:DataGrid.Columns> </sdk:DataGrid> </StackPanel> </UserControl>
ここまでで、サーバからデータを取得する設定が完了しました。早速、デバッグを実行してみましょう。検索の開始日と終了日を入力し、Loadボタンをクリックすると、結果が表示されます(図15)。クライアント側は、定義されたオブジェクトを単純に画面にドロップしただけで、検索画面が作成できます。
通常、SilverlightからWCFのサービスを呼び出すときには、WCFのサービス参照を作成し、Webサービスを非同期で呼び出す必要があります。しかし、WCF RIA Servicesのプロジェクトには、サービス参照は追加されておらず、Webサービスの呼び出しコードも存在しません。
これらの仕事を請け負っているのが自動生成コードです。Visual StudioのソリューションエクスプローラでSilverlightプロジェクトのすべてのファイルを表示してみましょう。
Generated_Codeフォルダの下に、コードファイルがあるのを確認できます。
実は、この自動生成されたコードファイルの中で、Webサービスの呼び出し、値の検証、エンティティーの宣言などが行われているのです。自動生成コードや値の検証については後編で詳しく取り上げます。