チュートリアル: RIA Services の概要
このチュートリアルでは、WCF RIA サービス の多くの機能の概要について説明します。このチュートリアルでは、AdventureWorks OLTP サンプル データベースのテーブルからデータを取得する RIA サービス アプリケーションを作成します。まず、LoadOperation を指定してデータを取得します。次に、DomainDataSource コントロールを使用してデータを取得します。データ プレゼンテーション コントロールの並べ替え、フィルター処理、およびページングを指定し、データの詳細ビューを表示する DataForm コントロールを追加します。フィールドに検証規則を適用し、ユーザーがデータ値を編集できるようにします。ドメイン操作へのアクセスを、認証されているユーザーに制限します。最後に、2 つの関連テーブル間の関連付けを定義し、関連データを表示します。
ヒント : |
---|
より基本的な RIA サービス ソリューションを作成して作業を開始する簡単なチュートリアルについては、「チュートリアル: RIA Services ソリューションの作成」または「チュートリアル: Silverlight ビジネス アプリケーション テンプレートの使用」を参照してください。 |
前提条件
このチュートリアル、および WCF RIA サービス のドキュメントで紹介されている他のチュートリアルでは、WCF RIA サービス および WCF RIA サービス Toolkit に加え、Visual Studio 2010 や Silverlight の開発者向けランタイムと SDK など、前提条件となっているいくつかのプログラムが適切にインストールおよび構成されている必要があります。また、SQL Server 2008 R2 Express with Advanced Services をインストールして構成し、AdventureWorks OLTP と LT データベースをインストールすることも必要です。
これらの各前提条件を満たしているかどうかを確認するための詳細な手順については、「WCF RIA Services の前提条件」ノード内のトピックを参照してください。このチュートリアルを進める前に、トピックに記載されている手順に従って、この RIA サービス チュートリアルを実行するときに発生する問題をできるだけ最小限に抑えるようにします。
ソリューションの作成および設定
このセクションでは、ソリューションを作成して設定します。
新しい WCF RIA Services アプリケーションを作成するには
Visual Studio 2010 で、[ファイル] メニューの [新規作成] をポイントし、[プロジェクト] をクリックして、新しい RIA サービス プロジェクトを作成します。
[新しいプロジェクト] ダイアログ ボックスが表示されます。
[インストールされたテンプレート] ペインで [Visual Basic] ノードまたは [Visual C#] ノードを展開し、[Silverlight] カテゴリをクリックします。
[Silverlight ビジネス アプリケーション] テンプレートをクリックし、HRApp という名前を付けます。
[OK] をクリックします。
作成されたソリューションの構造に注目してください。
ソリューションは、2 つのプロジェクト (HRApp という名前の Silverlight クライアント プロジェクトと、HRApp.Web という名前の ASP.NET Web アプリケーション サーバー プロジェクト) で構成されています。
既定のソリューションには、ナビゲーション、ユーザーのログインとログアウト、新規ユーザーの登録など、自動的に実装された多数の機能が含まれています。
アプリケーションをビルドして実行し (F5 キーを押し)、既定の実装を確認します。
Web ブラウザーを閉じます。
アプリケーションを設定するには
ソリューション エクスプローラーで、クライアント プロジェクトの MainPage.xaml を開きます。
XAML ビューで、
ApplicationNameTextBlock
という名前の TextBlock を確認します。次のマークアップに示すように、アプリケーション名はリソースから取得されます。
<TextBlock x:Name="ApplicationNameTextBlock" Style="{StaticResource ApplicationNameStyle}" Text="{Binding ApplicationStrings.ApplicationName, Source={StaticResource ResourceWrapper}}"/>
ソリューション エクスプローラーで、Assets フォルダーを展開し、Resources フォルダーを展開します。
ApplicationStrings.resx ファイルを開きます。
ApplicationName リソースを HR アプリケーションに変更します。
ApplicationStrings.resx ファイルを保存して閉じます。
ソリューション エクスプローラーで、Views フォルダーを右クリックし、[追加] をポイントして、[新しい項目] をクリックします。
[新しい項目の追加] ダイアログ ボックスが表示されます。
[インストールされたテンプレート] の [Silverlight] カテゴリで [Silverlight ページ] テンプレートをクリックし、EmployeeList.xaml という名前を付けます。
[追加] をクリックします。
EmployeeList.xaml が自動的に表示されない場合は、手動で開きます。
<Grid>
タグの間に次の XAML を追加します。<ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}" > <StackPanel x:Name="ContentStackPanel" Style="{StaticResource ContentStackPanelStyle}"> <TextBlock Text="Employee List" Style="{StaticResource HeaderTextStyle}"/> </StackPanel> </ScrollViewer>
EmployeeList.xaml ファイルを保存します。
MainPage.xaml を開きます。
2 つの既存のハイパーリンク ボタンの間に次の XAML を追加して、ページの上部に新しいハイパーリンク ボタンを追加します。
<HyperlinkButton x:Name="Link3" Style="{StaticResource LinkStyle}" NavigateUri="/EmployeeList" TargetName="ContentFrame" Content="Employee List"/> <Rectangle x:Name="Divider2" Style="{StaticResource DividerStyle}"/>
アプリケーションを実行し、ページ右上隅の [ホーム] リンクと [バージョン情報] リンクの間に新しい [従業員リスト] リンクが表示されていることを確認します。そのリンクをクリックして、ページの本文に "Employee List" を表示します。
データの表示
このセクションでは、AdventureWorks サンプル データベースのテーブルの ADO.NET Entity Data Model を作成します。次に、エンティティを公開してそのデータをクライアント プロジェクトに表示するドメイン サービスを作成します。
データ ソースを追加するには
ソリューション エクスプローラーで、HRApp.Web プロジェクトを右クリックし、[追加] をポイントして、[新しい項目] をクリックします。
[新しい項目の追加] ダイアログ ボックスが表示されます。
[データ] カテゴリで、[ADO.NET Entity Data Model] テンプレートをクリックします。
名前を AdventureWorks.edmx に変更し、[追加] をクリックします。
Entity Data Model ウィザードが開きます。
[モデルのコンテンツの選択] ページで、[データベースから生成] をクリックし、[次へ] をクリックします。
[データ接続の選択] ページで、AdventureWorks データベースへの接続を作成します。
エンティティ接続設定に AdventureWorks_DataEntities という名前を付け、[次へ] をクリックします。
[データベース オブジェクトの選択] ページで [テーブル] ノードを展開します。
Employee、PurchaseOrderDetail、および PurchaseOrderHeader の各テーブルのチェック ボックスをオンにします。
モデル名前空間に AdventureWorks_DataModel という名前を付け、[完了] をクリックします。
エンティティ データ モデルがデザイナーに表示されます。
ソリューションをビルドします。
ドメイン サービス オブジェクトとデータに対するクエリを追加するには
ソリューション エクスプローラーで、HRApp.Web プロジェクトを右クリックし、[追加] をポイントして、[新しい項目] をクリックします。
[新しい項目の追加] ダイアログ ボックスが表示されます。
[Web] カテゴリで、[DomainService クラス] テンプレートをクリックします。
新しい項目に OrganizationService という名前を付けます。
[追加] をクリックします。
[新しいドメイン サービス クラスの追加] ダイアログ ボックスで、[エンティティ] ボックスの一覧の [Employee]、[PurchaseOrderDetail]、および [PurchaseOrderHeader] のチェック ボックスをオンにし、各エンティティの [編集を有効にする] チェック ボックスをオンにします。
[クライアント アクセスを有効にする] チェック ボックスと [メタデータ用の関連クラスを生成する] チェック ボックスがオンになっていることを確認します。
[OK] をクリックします。
OrganizationService.cs/vb ファイルと OrganizationService.metadata.cs/vb ファイルがプロジェクトに追加されます。
OrganizationService.cs/vb ファイルを開きます。
エンティティごとにクエリ、挿入、更新、および削除メソッドが作成されていることを確認します。クエリ メソッドは、エンティティに対して必ず作成されます。挿入、更新、および削除メソッドは、[編集を有効にする] チェック ボックスをオンにしたため、追加されました。
生成されたコードを次のコードに置き換えて、EmployeeID で並べ替えられた従業員を返すように
GetEmployees()
クエリ メソッドをカスタマイズします。Public Function GetEmployees() As IQueryable(Of Employee) Return Me.ObjectContext.Employees.OrderBy(Function(e) e.EmployeeID) End Function
public IQueryable<Employee> GetEmployees() { return this.ObjectContext.Employees.OrderBy(e => e.EmployeeID); }
ソリューションをビルドします。
ソリューションをビルドすると、クライアント プロジェクトにドメイン コンテキストとエンティティが生成されます。
EmployeeList.xaml を開きます。
ツールボックスからデザイン ビューの TextBlock コントロールのすぐ下に、DataGrid コントロールをドラッグします。
DataGrid をデザイン ビューにドラッグすると、System.Windows.Controls.Data アセンブリへの参照が追加され、Page 要素に
sdk
というプレフィックスが追加されます。DataGrid コントロールの既定値を変更します。これを行うには、Height プロパティと Width プロパティを削除し、コントロールを読み取り専用にします。次に、列が自動的に生成されるように設定し、高さの最小値を設定します。
<sdk:DataGrid AutoGenerateColumns="True" IsReadOnly="True" Name="dataGrid1" MinHeight="100" />
EmployeeList.xaml を保存します。
EmployeeList.xaml.cs/vb を開きます。
次の using ステートメントまたは Imports ステートメントを追加します。
Imports System.ServiceModel.DomainServices.Client
using HRApp.Web; using System.ServiceModel.DomainServices.Client;
EmployeeList.xaml.cs/vb に次のコードを追加して、
OrganizationContext
クラスをインスタンス化し、従業員データを読み込みます。サーバー プロジェクトの
OrganizationService
クラスに基づいて、クライアント プロジェクトにOrganizationContext
クラスが自動的に生成されます。Partial Public Class EmployeeList Inherits Page Dim _OrganizationContext As New OrganizationContext Public Sub New() InitializeComponent() Me.dataGrid1.ItemsSource = _OrganizationContext.Employees _OrganizationContext.Load(_OrganizationContext.GetEmployeesQuery()) End Sub 'Executes when the user navigates to this page. Protected Overrides Sub OnNavigatedTo(ByVal e As System.Windows.Navigation.NavigationEventArgs) End Sub End Class
public partial class EmployeeList : Page { OrganizationContext _OrganizationContext = new OrganizationContext(); public EmployeeList() { InitializeComponent(); this.dataGrid1.ItemsSource = _OrganizationContext.Employees; _OrganizationContext.Load(_OrganizationContext.GetEmployeesQuery()); } // Executes when the user navigates to this page. protected override void OnNavigatedTo(NavigationEventArgs e) { } }
アプリケーションを実行します。
[Employee List] リンクをクリックして、DataGrid を表示します。
カスタム クエリを追加するには
HRApp.Web プロジェクトで、OrganizationService.cs/vb を開きます。
クラスの本文に次のコードを追加して、
GetSalariedEmployees
という名前の新しいメソッドを追加します。Public Function GetSalariedEmployees() As IQueryable(Of Employee) Return Me.ObjectContext.Employees.Where(Function(e) e.SalariedFlag = True).OrderBy(Function(e) e.EmployeeID) End Function
public IQueryable<Employee> GetSalariedEmployees() { return this.ObjectContext.Employees.Where(e => e.SalariedFlag == true).OrderBy(e => e.EmployeeID); }
ソリューションをビルドします。
クライアント プロジェクトで、EmployeeList.xaml.cs/vb を開きます。
コンストラクターで、
GetEmployeesQuery()
への呼び出しをGetSalariedEmployeesQuery()
への呼び出しに置き換えます。_OrganizationContext.Load(_OrganizationContext.GetSalariedEmployeesQuery())
_OrganizationContext.Load(_OrganizationContext.GetSalariedEmployeesQuery());
アプリケーションを実行し、[Employee List] リンクをクリックします。
表示されるすべての従業員の SalariedFlag 値がチェックされました。EmployeeID が 1、2、および 4 の従業員は給与を受け取っていないため、一覧に表示されなくなります。
ドメイン データ ソースを追加するには
EmployeeList.xaml を開きます。
ツールボックスからデザイン ビューの DataGrid のすぐ上に、DomainDataSource コントロールをドラッグします。DomainDataSource は、コントロールの一覧の下部に表示されることがあります。
ヒント : DomainDataSource コントロールがツールボックスに表示されない場合は、ツールボックス内を右クリックし、[アイテムの選択] をクリックします。[Silverlight コンポーネント] タブで [DomainDataSource] チェック ボックスをオンにし、[OK] をクリックします。 DomainDataSource コントロールをデザイン ビューにドラッグすると、Page 要素の System.Windows.Controls 名前空間に対して
riaControls
というプレフィックス付きの参照が作成されます。また、デザイン ビューの左下隅にデータ ソース アイコンが表示されます。C# ソリューションの場合、XAML ファイルに次の名前空間宣言を追加します。
xmlns:ds="clr-namespace:HRApp.Web"
Visual Basic ソリューションの場合、XAML ファイルに次の名前空間宣言を追加します。
xmlns:ds="clr-namespace:HRApp"
既存の XAML を次の XAML に置き換えて、DomainDataSource コントロールに
employeeDataSource
という名前を付け、LoadSize、AutoLoad、およびクエリ メソッドを設定します。<riaControls:DomainDataSource Name="employeeDataSource" LoadSize="20" QueryName="GetSalariedEmployees" AutoLoad="True"> </riaControls:DomainDataSource>
次の XAML を追加して、DomainDataSource の DomainContext を設定します。
<riaControls:DomainDataSource Name="employeeDataSource" LoadSize="20" QueryName="GetSalariedEmployees" AutoLoad="True"> <riaControls:DomainDataSource.DomainContext> <ds:OrganizationContext/> </riaControls:DomainDataSource.DomainContext> </riaControls:DomainDataSource>
DataGrid を次の XAML に置き換えます。
<sdk:DataGrid AutoGenerateColumns="True" IsReadOnly="True" Name="dataGrid1" MinHeight="100" Height="Auto" ItemsSource="{Binding Data, ElementName=employeeDataSource}" />
EmployeeList.xaml.cs/vb を開きます。
コンストラクターで、
OrganizationContext
インスタンスをインスタンス化するコード、GetSalariedEmployeesQuery()
への呼び出し、DataGrid コントロールの ItemsSource プロパティを設定するコードを削除するか、コメントにします。DomainDataSource によって自動的に実行されるため、データを明示的に読み込む必要はなくなりました。
'Dim _OrganizationContext As New OrganizationContext Public Sub New() InitializeComponent() 'Me.dataGrid1.ItemsSource = _OrganizationContext.Employees '_OrganizationContext.Load(_OrganizationContext.GetSalariedEmployeesQuery()) End Sub
//OrganizationContext _OrganizationContext = new OrganizationContext(); public EmployeeList() { InitializeComponent(); //this.dataGrid1.ItemsSource = _OrganizationContext.Employees; //_OrganizationContext.Load(_OrganizationContext.GetSalariedEmployeesQuery()); }
アプリケーションを実行し、[Employee List] リンクをクリックします。
アプリケーションが以前と同様に機能します。
データ ソースに並べ替え、フィルター処理、およびページングを追加するには
EmployeeList.xaml を開きます。
DomainDataSource で、次の SortDescriptors を追加して、DataGrid でのデータの並べ替え方法を指定します。
この XAML は、VacationHours 列を昇順に並べ替える方法を示しています。
<riaControls:DomainDataSource Name="employeeDataSource" LoadSize="20" QueryName="GetSalariedEmployees" AutoLoad="True"> <riaControls:DomainDataSource.DomainContext> <ds:OrganizationContext/> </riaControls:DomainDataSource.DomainContext> <riaControls:DomainDataSource.SortDescriptors> <riaControls:SortDescriptor PropertyPath="VacationHours" Direction="Ascending" /> </riaControls:DomainDataSource.SortDescriptors> </riaControls:DomainDataSource>
アプリケーションを実行し、[Employee List] リンクをクリックします。
VacationHours でデータが並べ替えられます。列ヘッダーをクリックして、並べ替えの方向を変更できます。
EmployeeList.xaml を開きます。
DataGrid の前に次の XAML を追加して、ユーザーが値を指定することによって返されるレコードをフィルター処理できるようにします。
この XAML によって TextBox コントロールが追加されるため、ユーザーは値を入力できます。
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left"> <TextBlock VerticalAlignment="Center" Text="Min Vacation Hours Filter" /> <TextBox x:Name="vacationHoursText" Width="75" FontSize="11" Margin="4" Text="0"/> </StackPanel>
DomainDataSource で、前の手順で追加した TextBox コントロールにバインドされるフィルター記述子を追加します。
<riaControls:DomainDataSource.FilterDescriptors> <riaControls:FilterDescriptor PropertyPath="VacationHours" Operator="IsGreaterThanOrEqualTo" IgnoredValue="" Value="{Binding ElementName=vacationHoursText, Path=Text}" > </riaControls:FilterDescriptor> </riaControls:DomainDataSource.FilterDescriptors>
アプリケーションを実行し、[Employee List] リンクをクリックします。
[Min Vacation Hours Filter] ボックスに「70」と入力します。
VacationHours が 70 以上の従業員が表示されていることを確認します。
EmployeeList.xaml を開きます。
ツールボックスから DataGrid のすぐ下に DataPager コントロールをドラッグします。
次の XAML に示すように、ページ サイズを 5 に設定し、ソースを設定します。
<sdk:DataPager PageSize="5" Source="{Binding Data, ElementName=employeeDataSource}" HorizontalAlignment="Left" />
アプリケーションを実行し、[Employee List] リンクをクリックします。
1 ページにつき 5 行のフィルター処理されたデータが表示され、DataGrid の下にページャー コントロールが表示されます。
マスター ビューと詳細ビューの作成
このセクションでは、Silverlight Toolkit に含まれている DataForm コントロールを使用してデータの詳細ビューを作成します。既定では、Silverlight ビジネス アプリケーション プロジェクト テンプレートの Libs フォルダーに System.Windows.Controls.Data.DataForm.Toolkit.dll バイナリが含まれています。
DataForm を追加するには
EmployeeList.xaml を開きます。
次の名前空間宣言を追加します。
xmlns:dataForm="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit"
DataPager コントロールの後に次の XAML を追加して、DataForm コントロールを追加します。
この XAML では、DataForm 属性を設定し、表示する列を指定します。
<dataForm:DataForm x:Name="dataForm1" Header="Employee Information" AutoGenerateFields="False" HorizontalAlignment="Left" AutoEdit="False" AutoCommit="False" Width="400" CurrentItem="{Binding SelectedItem, ElementName=dataGrid1}" Margin="0,12,0,0"> <dataForm:DataForm.EditTemplate> <DataTemplate> <StackPanel> <dataForm:DataField Label="Employee ID"> <TextBox IsReadOnly="True" Text="{Binding EmployeeID, Mode=OneWay}" /> </dataForm:DataField> <dataForm:DataField Label="Login ID"> <TextBox Text="{Binding LoginID, Mode=TwoWay}" /> </dataForm:DataField> <dataForm:DataField Label="Hire Date"> <TextBox Text="{Binding HireDate, Mode=TwoWay}" /> </dataForm:DataField> <dataForm:DataField Label="Marital Status"> <TextBox Text="{Binding MaritalStatus, Mode=TwoWay}" /> </dataForm:DataField> <dataForm:DataField Label="Gender"> <TextBox Text="{Binding Gender, Mode=TwoWay,NotifyOnValidationError=True, ValidatesOnExceptions=True }" /> </dataForm:DataField> <dataForm:DataField Label="Vacation Hours"> <TextBox Text="{Binding VacationHours, Mode=TwoWay,NotifyOnValidationError=True, ValidatesOnExceptions=True }" /> </dataForm:DataField> <dataForm:DataField Label="Sick Leave Hours"> <TextBox Text="{Binding SickLeaveHours, Mode=TwoWay,NotifyOnValidationError=True, ValidatesOnExceptions=True }" /> </dataForm:DataField> <dataForm:DataField Label="Active"> <CheckBox IsChecked="{Binding CurrentFlag, Mode=TwoWay,NotifyOnValidationError=True, ValidatesOnExceptions=True }" /> </dataForm:DataField> </StackPanel> </DataTemplate> </dataForm:DataForm.EditTemplate> </dataForm:DataForm>
アプリケーションを実行し、[Employee List] リンクをクリックします。
DataForm に DataGrid で選択した項目の詳細が表示されます。
データベースの更新
[新しいドメイン サービス クラスの追加] ダイアログ ボックスで [編集を有効にする] チェック ボックスをオンにすると、エンティティを更新、挿入、および削除するメソッドがドメイン サービス層に生成されます。このセクションでは、従業員リストのユーザー インターフェイスに編集ボタンを追加して、ユーザーがこれらの操作を実行できるようにします。
レコードを更新するには
EmployeeList.xaml ファイルを開きます。
DataForm コントロールの後に次の XAML を追加して、[Submit] ボタンを追加します。
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="0,12,0,0"> <Button x:Name="submitButton" Width="75" Height="23" Content="Submit" Margin="4,0,0,0" Click="submitButton_Click"/> </StackPanel>
DomainDataSource コントロールで、SubmittedChanges イベントのイベント ハンドラーを指定します。
<riaControls:DomainDataSource Name="employeeDataSource" LoadSize="20" QueryName="GetSalariedEmployees" AutoLoad="True" SubmittedChanges="employeeDataSource_SubmittedChanges">
EmployeeList.xaml.cs/vb を開きます。
ボタン クリック イベントの次のイベント ハンドラーを追加します。
操作の処理中、ユーザーが再び変更を送信できないようにするために、
submitButton
を無効にします。Private Sub submitButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) submitButton.IsEnabled = False employeeDataSource.SubmitChanges() End Sub
private void submitButton_Click(object sender, RoutedEventArgs e) { submitButton.IsEnabled = false; employeeDataSource.SubmitChanges(); }
送信操作が正常に完了したかどうかを確認して
submitButton
を有効にする SubmittedChanges イベントのイベント ハンドラーを追加します。Private Sub employeeDataSource_SubmittedChanges(ByVal sender As System.Object, ByVal e As System.Windows.Controls.SubmittedChangesEventArgs) If (e.HasError) Then MessageBox.Show(String.Format("Changes were not saved: {0}", e.Error.Message)) e.MarkErrorAsHandled() End If submitButton.IsEnabled = True End Sub
private void employeeDataSource_SubmittedChanges(object sender, SubmittedChangesEventArgs e) { if (e.HasError) { MessageBox.Show(string.Format("Changes were not saved: {0}", e.Error.Message)); e.MarkErrorAsHandled(); } submitButton.IsEnabled = true; }
アプリケーションを実行し、[Employee List] リンクをクリックします。
従業員を選択し、データ フォームの右上隅にある鉛筆のアイコンをクリックして編集を有効にします。
これで、編集可能なフィールドを変更できます。
従業員データを変更し、[OK] をクリックします。
[Submit] をクリックしてデータを保存します。
サーバーのデータベースに変更が保存されるのは、[Submit] をクリックした場合のみです。
ドメイン サービスにカスタム メソッドを追加するには
HRApp.Web サーバー プロジェクトで、OrganizationService.cs/vb ファイルを開きます。
ApproveSabbatical
という名前の次のカスタム メソッドを追加します。Public Sub ApproveSabbatical(ByVal current As Employee) Me.ObjectContext.Employees.AttachAsModified(current) current.CurrentFlag = False End Sub
public void ApproveSabbatical(Employee current) { // Start custom workflow here this.ObjectContext.Employees.AttachAsModified(current); current.CurrentFlag = false; }
ソリューションをビルドします。
EmployeeList.xaml を開きます。
[Submit] ボタンの後に次の XAML を追加して、[Approve Sabbatical] ボタンを追加します。
<Button x:Name="approveSabbatical" Width="115" Height="23" Content="Approve Sabbatical" Margin="4,0,0,0" Click="approveSabbatical_Click"/>
EmployeeList.xaml.cs/vb を開きます。
ApproveSabbatical ドメイン操作を呼び出す、ボタン クリック イベントの次のイベント ハンドラーを追加します。
Private Sub approveSabbatical_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Dim luckyEmployee As Employee luckyEmployee = dataGrid1.SelectedItem luckyEmployee.ApproveSabbatical() employeeDataSource.SubmitChanges() End Sub
private void approveSabbatical_Click(object sender, RoutedEventArgs e) { Employee luckyEmployee = (Employee)(dataGrid1.SelectedItem); luckyEmployee.ApproveSabbatical(); employeeDataSource.SubmitChanges(); }
アプリケーションを実行し、[Employee List] リンクをクリックします。
[Approve Sabbatical] をクリックし、選択した従業員の [CurrentFlag] チェック ボックスがオフになっていることを確認します。
データの検証
DataForm コントロールには、データ アクセス層 (DAL) で発生した検証エラーを表示できます。たとえば、VacationHours フィールドに整数以外の値を入力した場合、検証エラーが表示されます。検証動作の例を次の図に示します。
[新しいドメイン サービス クラスの追加] ダイアログ ボックスで [メタデータ用の関連クラスを生成する] チェック ボックスをオンにすると、メタデータを含むファイルが作成されます。このチュートリアルでは、メタデータ ファイルに OrganizationService.metadata.cs/vb という名前を付けます。このセクションでは、そのファイルに検証属性を追加します。クライアント プロジェクトとサーバー プロジェクトに、検証規則が適用されます。
また、データベースに新しい従業員レコードを追加できるユーザー インターフェイスも作成します。前のセクションで追加した検証規則は、新しいユーザー インターフェイスに自動的に適用されます。
基本的な検証を追加するには
HRApp.web プロジェクトで、OrganizationService.metadata.cs/vb を開きます。
Gender
プロパティとVacationHours
プロパティに次の属性を追加します。<Required()> _ Public Property Gender As String <Range(0, 70)> _ Public Property VacationHours As Short
[Required] public string Gender { get; set; } [Range(0, 70)] public short VacationHours { get; set; }
ソリューションをビルドします。
アプリケーションを実行し、[Employee List] リンクをクリックします。
従業員を選択し、データ フォームの右上隅にある鉛筆のアイコンをクリックして編集を有効にします。
Vacation Hours フィールドに有効範囲 (0 ~ 70) 外の値を入力し、別のコントロールにフォーカスを移動します。
休暇時間数に関する検証エラーが表示されます。
Gender フィールドの値を削除し、別のコントロールにフォーカスを移動します。
性別に関する検証エラーが表示されます。
カスタム検証を追加するには
ソリューション エクスプローラーで、HRApp.Web プロジェクトを右クリックし、[追加] をポイントして、[新しい項目] をクリックします。
[新しい項目の追加] ダイアログ ボックスが表示されます。
[コード] カテゴリで、[コード ファイル] テンプレートをクリックします。
新しい項目に OrganizationService.shared.cs または OrganizationService.shared.vb という名前を付けます。
ファイル名の末尾が
.shared.cs
または.shared.vb
のファイルは、クライアント プロジェクトとサーバー プロジェクトの両方で使用できます。共有ファイルを使用すると、両方のプロジェクトで同じ検証規則を実行できます。後の手順でソリューションをビルドした後、クライアントの Generated_Code という隠しフォルダーを調べると、OrganizationService.shared.cs/vb ファイルを確認できます。[追加] をクリックします。
共有ファイルに次のコードを追加して、
Gender
プロパティに割り当てられている値を確認する、カスタマイズされた検証クラスを作成します。Imports System Imports System.ComponentModel.DataAnnotations Public Module GenderValidator Public Function IsGenderValid(ByVal gender As String, ByVal context As ValidationContext) As ValidationResult If gender = "M" OrElse gender = "m" OrElse gender = "F" OrElse gender = "f" Then Return ValidationResult.Success Else Return New ValidationResult("The Gender field only has two valid values 'M'/'F'", New String() {"Gender"}) End If End Function End Module
using System; using System.ComponentModel.DataAnnotations; namespace HRApp.Web { public static class GenderValidator { public static ValidationResult IsGenderValid(string gender, ValidationContext context) { if (gender == "M" || gender == "m" || gender == "F" || gender == "f") { return ValidationResult.Success; } else { return new ValidationResult("The Gender field only has two valid values 'M'/'F'", new string[] { "Gender" }); } } } }
OrganizationService.metadata.cs/vb を開きます。
Gender
プロパティに次のカスタム検証属性を追加します。<Required()> _ <CustomValidation(GetType(GenderValidator), "IsGenderValid")> _ Public Property Gender As String
[CustomValidation(typeof(HRApp.Web.GenderValidator), "IsGenderValid")] [Required] public string Gender { get; set; }
ソリューションをビルドします。
アプリケーションを実行し、[Employee List] リンクをクリックします。
従業員を選択し、データ フォームの右上隅にある鉛筆のアイコンをクリックして編集を有効にします。
Gender フィールドに M または F 以外の値を入力し、別のコントロールにフォーカスを移動します。
カスタム検証の結果が表示されます。
新しいレコードの追加
このセクションでは、ユーザーが Employee テーブルに新しいレコードを作成できるようにするフォームを追加します。
新しいレコードを追加するには
HRApp プロジェクトに新しい項目を追加します。
[Silverlight] カテゴリで、[Silverlight 子ウィンドウ] テンプレートをクリックします。
新しい項目に EmployeeRegistrationWindow.xaml という名前を付けます。
[追加] をクリックします。
EmployeeRegistrationWindow.xaml.cs/vb を開きます。
C# を使用している場合は、次の using ステートメントを追加します。
using HRApp.Web;
ユーザー値を使用して作成される新しい
Employee
エンティティのプロパティを追加します。Public Property NewEmployee As Employee
public Employee NewEmployee { get; set; }
EmployeeRegistrationWindow.xaml を開きます。
EmployeeRegistrationWindow.xaml に次の名前空間宣言を追加して、このウィンドウの DataForm コントロールを使用します。
xmlns:dataForm="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit"
EmployeeRegistrationWindow.xaml の [Cancel] ボタンの直前に、次の DataForm コントロールを追加します。
<dataForm:DataForm x:Name="addEmployeeDataForm" AutoGenerateFields="False" AutoCommit="True" AutoEdit="True" CommandButtonsVisibility="None"> <dataForm:DataForm.EditTemplate> <DataTemplate> <StackPanel> <dataForm:DataField Label="Login ID"> <TextBox Text="{Binding LoginID, Mode=TwoWay}" /> </dataForm:DataField> <dataForm:DataField Label="National ID"> <TextBox Text="{Binding NationalIDNumber, Mode=TwoWay}" /> </dataForm:DataField> <dataForm:DataField Label="Title"> <TextBox Text="{Binding Title, Mode=TwoWay}" /> </dataForm:DataField> <dataForm:DataField Label="Marital Status"> <TextBox Text="{Binding MaritalStatus, Mode=TwoWay}" /> </dataForm:DataField> <dataForm:DataField Label="Gender"> <TextBox Text="{Binding Gender, Mode=TwoWay,NotifyOnValidationError=True, ValidatesOnExceptions=True }" /> </dataForm:DataField> <dataForm:DataField Label="Salaried"> <CheckBox IsChecked="{Binding SalariedFlag, Mode=TwoWay,NotifyOnValidationError=True, ValidatesOnExceptions=True }" /> </dataForm:DataField> <dataForm:DataField Label="Active"> <CheckBox IsChecked="{Binding CurrentFlag, Mode=TwoWay,NotifyOnValidationError=True, ValidatesOnExceptions=True }" /> </dataForm:DataField> </StackPanel> </DataTemplate> </dataForm:DataForm.EditTemplate> </dataForm:DataForm>
EmployeeRegistrationWindow.xaml.cs/vb を開きます。
新しい
Employee
インスタンスを作成し、新しいインスタンスのコミットまたは挿入の取り消しを処理するために、次のコードを追加します。Partial Public Class EmployeeRegistrationWindow Inherits ChildWindow Public Sub New() InitializeComponent() NewEmployee = New Employee addEmployeeDataForm.CurrentItem = NewEmployee addEmployeeDataForm.BeginEdit() End Sub Public Property NewEmployee As Employee Private Sub OKButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles OKButton.Click Me.addEmployeeDataForm.CommitEdit() Me.DialogResult = True End Sub Private Sub CancelButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles CancelButton.Click NewEmployee = Nothing addEmployeeDataForm.CancelEdit() Me.DialogResult = False End Sub End Class
public partial class EmployeeRegistrationWindow : ChildWindow { public EmployeeRegistrationWindow() { InitializeComponent(); NewEmployee = new Employee(); addEmployeeDataForm.CurrentItem = NewEmployee; addEmployeeDataForm.BeginEdit(); } public Employee NewEmployee { get; set; } private void OKButton_Click(object sender, RoutedEventArgs e) { addEmployeeDataForm.CommitEdit(); this.DialogResult = true; } private void CancelButton_Click(object sender, RoutedEventArgs e) { NewEmployee = null; addEmployeeDataForm.CancelEdit(); this.DialogResult = false; } }
EmployeeList.xaml を開きます。
DataPager と DataForm の間に次の XAML を追加して、
addNewEmployee
という名前のボタンを作成します。<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="0,12,0,0"> <Button x:Name="addNewEmployee" Width="90" Height="23" Content="Add Employee" Margin="4,0,0,0" Click="addNewEmployee_Click"/> </StackPanel>
EmployeeList.xaml.cs/vb を開きます。
ボタン クリック イベントを処理し、EmployeeRegistrationWindow を表示するために、次のコードを追加します。
Private Sub addNewEmployee_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Dim addEmp As New EmployeeRegistrationWindow() AddHandler addEmp.Closed, AddressOf addEmp_Closed addEmp.Show() End Sub
private void addNewEmployee_Click(object sender, RoutedEventArgs e) { EmployeeRegistrationWindow addEmp = new EmployeeRegistrationWindow(); addEmp.Closed += new EventHandler(addEmp_Closed); addEmp.Show(); }
EmployeeRegistrationWindow の closed イベントを処理するために、次のメソッドを追加します。
Private Sub addEmp_Closed(ByVal sender As Object, ByVal e As System.EventArgs) Dim emp As EmployeeRegistrationWindow = sender If Not emp.NewEmployee Is Nothing Then Dim _OrganizationContext As OrganizationContext = employeeDataSource.DomainContext _OrganizationContext.Employees.Add(emp.NewEmployee) employeeDataSource.SubmitChanges() End If End Sub
void addEmp_Closed(object sender, EventArgs e) { EmployeeRegistrationWindow emp = (EmployeeRegistrationWindow)sender; if (emp.NewEmployee != null) { OrganizationContext _OrganizationContext = (OrganizationContext)(employeeDataSource.DomainContext); _OrganizationContext.Employees.Add(emp.NewEmployee); employeeDataSource.SubmitChanges(); } }
OrganizationService.cs/vb を開きます。
次のコードを追加して、
InsertEmployee
メソッドを変更します。Public Sub InsertEmployee(ByVal employee As Employee) employee.HireDate = DateTime.Now employee.ModifiedDate = DateTime.Now employee.VacationHours = 0 employee.SickLeaveHours = 0 employee.rowguid = Guid.NewGuid() employee.ContactID = 1001 employee.BirthDate = New DateTime(1967, 3, 18) If ((employee.EntityState = EntityState.Detached) _ = False) Then Me.ObjectContext.ObjectStateManager.ChangeObjectState(employee, EntityState.Added) Else Me.ObjectContext.Employees.AddObject(employee) End If End Sub
public void InsertEmployee(Employee employee) { employee.HireDate = DateTime.Now; employee.ModifiedDate = DateTime.Now; employee.VacationHours = 0; employee.SickLeaveHours = 0; employee.rowguid = Guid.NewGuid(); employee.ContactID = 1001; employee.BirthDate = new DateTime(1967, 3, 18); if ((employee.EntityState != EntityState.Detached)) { this.ObjectContext.ObjectStateManager.ChangeObjectState(employee, EntityState.Added); } else { this.ObjectContext.Employees.AddObject(employee); } }
アプリケーションを実行し、[Employee List] リンクをクリックします。
[Add Employee] をクリックします。
EmployeeRegistrationWindow が開きます。
ウィンドウでデータを追加し、[Salaried] チェック ボックスをオンにします。
[OK] をクリックします。
ページを更新し、DataGrid に新しい従業員が表示されることを確認します。
ユーザーの認証
このセクションでは、ApproveSabbatical
メソッドへのアクセスを、認証されているユーザーのみに制限します。
認証を追加するには
OrganizationService.cs/vb を開きます。
ApproveSabbatical
メソッドに RequiresAuthentication 属性を追加します。ドメイン操作に RequiresAuthentication 属性を適用すると、認証されているユーザーのみが操作を呼び出すことができます。匿名ユーザーが [Approve Sabbatical] をクリックした場合、操作は実行されません。
<RequiresAuthentication()> _ Public Sub ApproveSabbatical(ByVal current As Employee) Me.ObjectContext.Employees.AttachAsModified(current) current.CurrentFlag = False End Sub
[RequiresAuthentication] public void ApproveSabbatical(Employee current) { // Start custom workflow here this.ObjectContext.Employees.AttachAsModified(current); current.CurrentFlag = false; }
EmployeeList.xaml.cs/vb を開きます。
次の using ステートメントまたは Imports ステートメントを追加します。
Imports System.ServiceModel.DomainServices.Client.ApplicationServices Imports HRApp.LoginUI
using System.ServiceModel.DomainServices.Client.ApplicationServices; using HRApp.LoginUI;
ユーザーが認証されているかどうかを確認するために、
approveSabbatical_Click
メソッドを変更し、LoggedIn ハンドラーを追加します。Private Sub approveSabbatical_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) If WebContext.Current.User IsNot Nothing AndAlso WebContext.Current.User.IsAuthenticated Then Dim luckyEmployee As Employee = dataGrid1.SelectedItem luckyEmployee.ApproveSabbatical() employeeDataSource.SubmitChanges() Else AddHandler WebContext.Current.Authentication.LoggedIn, AddressOf Current_LoginCompleted Dim newWindow As New LoginRegistrationWindow newWindow.Show() End If End Sub Private Sub Current_LoginCompleted(ByVal sender As Object, ByVal e As AuthenticationEventArgs) Dim luckyEmployee As Employee = dataGrid1.SelectedItem luckyEmployee.ApproveSabbatical() employeeDataSource.SubmitChanges() RemoveHandler WebContext.Current.Authentication.LoggedIn, AddressOf Current_LoginCompleted End Sub
private void approveSabbatical_Click(object sender, RoutedEventArgs e) { if (WebContext.Current.User.IsAuthenticated) { Employee luckyEmployee = (Employee)(dataGrid1.SelectedItem); luckyEmployee.ApproveSabbatical(); employeeDataSource.SubmitChanges(); } else { WebContext.Current.Authentication.LoggedIn += Authentication_LoggedIn; new LoginRegistrationWindow().Show(); } } private void Authentication_LoggedIn(object sender, AuthenticationEventArgs e) { Employee luckyEmployee = (Employee)(dataGrid1.SelectedItem); luckyEmployee.ApproveSabbatical(); employeeDataSource.SubmitChanges(); WebContext.Current.Authentication.LoggedIn -= Authentication_LoggedIn; }
アプリケーションを実行し、[Employee List] リンクをクリックします。
従業員レコードを選択し、[Approve Sabbatical] をクリックします。
ログイン ウィンドウにリダイレクトされます。
[今すぐ登録] リンクをクリックします。
必須フィールドに入力して、新しいアカウントを作成します。
[OK] をクリックします。
指定したアカウントでログインした状態になり、ナビゲーション リンクの下のバーに名前が表示されます。
関連データの表示
RIA サービス を使用すると、関連テーブルのデータを容易に操作できます。このセクションでは、新しい Silverlight ページを追加し、PurchaseOrderHeader テーブルと PurchaseOrderDetail テーブルのデータを表示します。また、データ変更操作をカスタマイズして、関連データが共に変更されるようにすることもできます。ドメイン操作によって関連テーブルのデータを変更する方法の例については、「合成階層」を参照してください。
関連テーブルのデータを表示するには
HRApp プロジェクトで、Views フォルダーを右クリックし、[追加] をポイントして、[新しい項目] をクリックします。
PurchaseOrders.xaml という名前の新しい Silverlight ページを追加します。
PurchaseOrders.xaml を開きます。
<Grid>
タグの間に次の XAML を追加します。<ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}" > <StackPanel x:Name="ContentStackPanel" Style="{StaticResource ContentStackPanelStyle}"> <TextBlock Text="Purchase Orders" Style="{StaticResource HeaderTextStyle}"/> </StackPanel> </ScrollViewer>
MainPage.xaml を開きます。
EmployeeList リンクの後に次の XAML を追加して、PurchaseOrders ページへのリンクを含めます。
<Rectangle x:Name="Divider3" Style="{StaticResource DividerStyle}"/> <HyperlinkButton x:Name="Link4" Style="{StaticResource LinkStyle}" NavigateUri="/PurchaseOrders" TargetName="ContentFrame" Content="Purchase Orders"/>
OrganizationService.metadata.cs/vb を開きます。
PurchaseOrderHeaderMetadata
クラスのPurchaseOrderDetails
プロパティに Include 属性と Composition 属性を追加します。<Include()> _ <Composition()> _ Public Property PurchaseOrderDetails As EntityCollection(Of PurchaseOrderDetail)
[Include] [Composition] public EntityCollection<PurchaseOrderDetail> PurchaseOrderDetails { get; set; }
OrganizationService.cs/vb を開きます。
GetPurchaseOrderHeaders
メソッドを変更して、PurchaseOrderDetails
の関連レコードもこのクエリで取得されるようにします。Public Function GetPurchaseOrderHeaders() As IQueryable(Of PurchaseOrderHeader) Return Me.ObjectContext.PurchaseOrderHeaders.Include("PurchaseOrderDetails").OrderBy(Function(p) p.PurchaseOrderID) End Function
public IQueryable<PurchaseOrderHeader> GetPurchaseOrderHeaders() { return this.ObjectContext.PurchaseOrderHeaders.Include("PurchaseOrderDetails").OrderBy(p => p.PurchaseOrderID); }
PurchaseOrders.xaml を開きます。
[データ] メニューの [データ ソースの表示] をクリックして [データ ソース] ウィンドウを開きます。
PurchaseOrders.xaml のデザイン サーフェイスに [PurchaseOrderHeader] ノードをドラッグします。
PurchaseOrderHeader テーブルの列を含む DataGrid が表示されます。
[データ ソース] ウィンドウで [PurchaseOrderHeader] ノードを展開します。
デザイン サーフェイスの PurchaseOrderHeader の DataGrid のすぐ下に、[PurchaseOrderHeader] ノード内にある [PurchaseOrderDetails] ノードをドラッグします。
PurchaseOrderDetails テーブルの列を含む DataGrid が表示されます。
XAML ビューで、
PurchaseOrderHeader
およびPurchaseOrderDetails
の DataGrid コントロールを確認します。各 DataGrid から
Width=”400”
プロパティを削除して、利用可能な幅いっぱいに表示されるようにします。PurchaseOrderHeader の DataGrid の前に次の TextBlock コントロールを追加して、データにラベルを設定します。
<TextBlock Text="Order Headers"></TextBlock>
PurchaseOrderDetails の DataGrid の前に次の TextBlock コントロールを追加して、データにラベルを設定します。
<TextBlock Text="Order Details"></TextBlock>
DomainDataSource コントロールに次のフィルター記述子を追加して、取得されるレコードの数を制限します。
<riaControls:DomainDataSource.FilterDescriptors> <riaControls:FilterDescriptor PropertyPath="PurchaseOrderID" Operator="IsLessThan" Value="10"></riaControls:FilterDescriptor> </riaControls:DomainDataSource.FilterDescriptors>
PurchaseOrders.xaml の完全な XAML を次に示します。
<navigation:Page x:Class="HRApp.Views.PurchaseOrders" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="https://schemas.microsoft.com/expression/blend/2008" xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation" d:DesignWidth="640" d:DesignHeight="480" Title="PurchaseOrders Page" xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.DomainServices" xmlns:my="clr-namespace:HRApp.Web" xmlns:sdk="https://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"> <sdk:Page.Resources> <CollectionViewSource x:Key="purchaseOrderHeaderPurchaseOrderDetailsViewSource" Source="{Binding Path=Data.PurchaseOrderDetails, ElementName=purchaseOrderHeaderDomainDataSource}" /> </sdk:Page.Resources> <Grid x:Name="LayoutRoot"> <ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}" > <StackPanel x:Name="ContentStackPanel" Style="{StaticResource ContentStackPanelStyle}"> <TextBlock Text="Purchase Orders" Style="{StaticResource HeaderTextStyle}"/> <riaControls:DomainDataSource AutoLoad="True" d:DesignData="{d:DesignInstance my:PurchaseOrderHeader, CreateList=true}" Height="0" LoadedData="purchaseOrderHeaderDomainDataSource_LoadedData_1" Name="purchaseOrderHeaderDomainDataSource" QueryName="GetPurchaseOrderHeadersQuery" Width="0"> <riaControls:DomainDataSource.DomainContext> <my:OrganizationContext /> </riaControls:DomainDataSource.DomainContext> <riaControls:DomainDataSource.FilterDescriptors> <riaControls:FilterDescriptor PropertyPath="PurchaseOrderID" Operator="IsLessThan" Value="10"></riaControls:FilterDescriptor> </riaControls:DomainDataSource.FilterDescriptors> </riaControls:DomainDataSource> <TextBlock Text="Order Headers"></TextBlock> <sdk:DataGrid AutoGenerateColumns="False" Height="200" ItemsSource="{Binding ElementName=purchaseOrderHeaderDomainDataSource, Path=Data}" Name="purchaseOrderHeaderDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected"> <sdk:DataGrid.Columns> <sdk:DataGridTextColumn x:Name="employeeIDColumn" Binding="{Binding Path=EmployeeID}" Header="Employee ID" Width="SizeToHeader" /> <sdk:DataGridTextColumn x:Name="freightColumn" Binding="{Binding Path=Freight}" Header="Freight" Width="SizeToHeader" /> <sdk:DataGridTemplateColumn x:Name="modifiedDateColumn" Header="Modified Date" Width="SizeToHeader"> <sdk:DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <sdk:DatePicker SelectedDate="{Binding Path=ModifiedDate, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" /> </DataTemplate> </sdk:DataGridTemplateColumn.CellEditingTemplate> <sdk:DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding Path=ModifiedDate, StringFormat=\{0:d\}}" /> </DataTemplate> </sdk:DataGridTemplateColumn.CellTemplate> </sdk:DataGridTemplateColumn> <sdk:DataGridTemplateColumn x:Name="orderDateColumn" Header="Order Date" Width="SizeToHeader"> <sdk:DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <sdk:DatePicker SelectedDate="{Binding Path=OrderDate, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" /> </DataTemplate> </sdk:DataGridTemplateColumn.CellEditingTemplate> <sdk:DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding Path=OrderDate, StringFormat=\{0:d\}}" /> </DataTemplate> </sdk:DataGridTemplateColumn.CellTemplate> </sdk:DataGridTemplateColumn> <sdk:DataGridTextColumn x:Name="purchaseOrderIDColumn" Binding="{Binding Path=PurchaseOrderID, Mode=OneWay}" Header="Purchase Order ID" IsReadOnly="True" Width="SizeToHeader" /> <sdk:DataGridTextColumn x:Name="revisionNumberColumn" Binding="{Binding Path=RevisionNumber}" Header="Revision Number" Width="SizeToHeader" /> <sdk:DataGridTemplateColumn x:Name="shipDateColumn" Header="Ship Date" Width="SizeToHeader"> <sdk:DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <sdk:DatePicker SelectedDate="{Binding Path=ShipDate, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true, TargetNullValue=''}" /> </DataTemplate> </sdk:DataGridTemplateColumn.CellEditingTemplate> <sdk:DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding Path=ShipDate, StringFormat=\{0:d\}}" /> </DataTemplate> </sdk:DataGridTemplateColumn.CellTemplate> </sdk:DataGridTemplateColumn> <sdk:DataGridTextColumn x:Name="shipMethodIDColumn" Binding="{Binding Path=ShipMethodID}" Header="Ship Method ID" Width="SizeToHeader" /> <sdk:DataGridTextColumn x:Name="statusColumn" Binding="{Binding Path=Status}" Header="Status" Width="SizeToHeader" /> <sdk:DataGridTextColumn x:Name="subTotalColumn" Binding="{Binding Path=SubTotal}" Header="Sub Total" Width="SizeToHeader" /> <sdk:DataGridTextColumn x:Name="taxAmtColumn" Binding="{Binding Path=TaxAmt}" Header="Tax Amt" Width="SizeToHeader" /> <sdk:DataGridTextColumn x:Name="totalDueColumn" Binding="{Binding Path=TotalDue}" Header="Total Due" Width="SizeToHeader" /> <sdk:DataGridTextColumn x:Name="vendorIDColumn" Binding="{Binding Path=VendorID}" Header="Vendor ID" Width="SizeToHeader" /> </sdk:DataGrid.Columns> </sdk:DataGrid> <TextBlock Text="Order Details"></TextBlock> <sdk:DataGrid AutoGenerateColumns="False" Height="200" ItemsSource="{Binding Source={StaticResource purchaseOrderHeaderPurchaseOrderDetailsViewSource}}" Name="purchaseOrderDetailsDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected"> <sdk:DataGrid.Columns> <sdk:DataGridTemplateColumn x:Name="dueDateColumn" Header="Due Date" Width="SizeToHeader"> <sdk:DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <sdk:DatePicker SelectedDate="{Binding Path=DueDate, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" /> </DataTemplate> </sdk:DataGridTemplateColumn.CellEditingTemplate> <sdk:DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding Path=DueDate, StringFormat=\{0:d\}}" /> </DataTemplate> </sdk:DataGridTemplateColumn.CellTemplate> </sdk:DataGridTemplateColumn> <sdk:DataGridTextColumn x:Name="lineTotalColumn" Binding="{Binding Path=LineTotal}" Header="Line Total" Width="SizeToHeader" /> <sdk:DataGridTemplateColumn x:Name="modifiedDateColumn1" Header="Modified Date" Width="SizeToHeader"> <sdk:DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <sdk:DatePicker SelectedDate="{Binding Path=ModifiedDate, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" /> </DataTemplate> </sdk:DataGridTemplateColumn.CellEditingTemplate> <sdk:DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding Path=ModifiedDate, StringFormat=\{0:d\}}" /> </DataTemplate> </sdk:DataGridTemplateColumn.CellTemplate> </sdk:DataGridTemplateColumn> <sdk:DataGridTextColumn x:Name="orderQtyColumn" Binding="{Binding Path=OrderQty}" Header="Order Qty" Width="SizeToHeader" /> <sdk:DataGridTextColumn x:Name="productIDColumn" Binding="{Binding Path=ProductID}" Header="Product ID" Width="SizeToHeader" /> <sdk:DataGridTextColumn x:Name="purchaseOrderDetailIDColumn" Binding="{Binding Path=PurchaseOrderDetailID}" Header="Purchase Order Detail ID" Width="SizeToHeader" /> <sdk:DataGridTextColumn x:Name="purchaseOrderIDColumn1" Binding="{Binding Path=PurchaseOrderID}" Header="Purchase Order ID" Width="SizeToHeader" /> <sdk:DataGridTextColumn x:Name="receivedQtyColumn" Binding="{Binding Path=ReceivedQty}" Header="Received Qty" Width="SizeToHeader" /> <sdk:DataGridTextColumn x:Name="rejectedQtyColumn" Binding="{Binding Path=RejectedQty}" Header="Rejected Qty" Width="SizeToHeader" /> <sdk:DataGridTextColumn x:Name="stockedQtyColumn" Binding="{Binding Path=StockedQty}" Header="Stocked Qty" Width="SizeToHeader" /> <sdk:DataGridTextColumn x:Name="unitPriceColumn" Binding="{Binding Path=UnitPrice}" Header="Unit Price" Width="SizeToHeader" /> </sdk:DataGrid.Columns> </sdk:DataGrid> </StackPanel> </ScrollViewer> </Grid> </navigation:Page>
アプリケーションを実行し、[Purchase Orders] リンクをクリックします。
PurchaseOrderHeader の DataGrid で別のレコードを選択します。
PurchaseOrderDetail の関連レコードが自動的に表示されることを確認します。
次の手順
このチュートリアルでは、RIA サービス の多くの機能について説明しました。特定の領域の詳細については、このドキュメントで紹介している他のチュートリアルを参照してください。
参照
処理手順
チュートリアル: Silverlight ビジネス アプリケーションにおけるデータ表示
チュートリアル: Silverlight ビジネス アプリケーションでの認証サービスの使用