ページ

2012年10月29日月曜日

◆RIAサービスを使ってデータ表示2

前回MTG Blog: ◆RIAサービスを使ってデータ表示(VS2012)の続き。

<データの表示をカスタマイズする>

カスタムクエリを追加するには

  1. RIA1.Webプロジェクトの「MyService.cs」を開き、以下の「GetEmployeesInLongon」メソッドを追加する。
    1. public IQueryable<Employees> GetEmployeesInLondon()
    2. {
    3.     return this.ObjectContext.Employees.Where(e => e.City == "London");
    4. }
  2. ビルド
  3. RIA1プロジェクトの「EmployeeList.xaml.cs」を開き「GetEmployeesQuery」メソッドを今作成した「GetEmployeesInLondonQuery」メソッドに置き換える。
    1. public EmployeeList()
    2. {
    3.     InitializeComponent();
    4.     this.dataGrid1.ItemsSource = _MyContext.Employees;
    5.     //_MyContext.Load(_MyContext.GetEmployeesQuery());
    6.     _MyContext.Load(_MyContext.GetEmployeesInLondonQuery());
    7.  
    8. }
  4. これで実行して「EmployeeList」を開くと以下のように「London」のみのデータが表示される。
    image

「DomainDataSource」コントロールを使ってデータをロードする

これまではコードビハインドへのコーディング追加によって、「Employee」テーブルの内容をロードしていたが、「DomainDataSource」なるコントロールを使ってXAMLのみでデータをロードする方法が用意されている。(GUIでクエリーデータソースをドラッグアンドドロップなどして自動生成させるとVisualStudioはこいつを使うようである)

「DomainDataSource」を使ったデータ読み込みの方法を試してみる。

  1. RIA1プロジェクトの「EmployeeList.xaml.cs」を開きデータロードのロジックをコメントアウト。
    1. public EmployeeList()
    2. {
    3.     InitializeComponent();
    4.     //this.dataGrid1.ItemsSource = _MyContext.Employees;
    5.     //_MyContext.Load(_MyContext.GetEmployeesQuery());
    6.     //_MyContext.Load(_MyContext.GetEmployeesInLondonQuery());
    7.  
    8. }
  2. RIA1プロジェクトの「EmployeeList.xaml」を開き、ツールボックスからデザインビューの「DataGrid」のすぐ上に「DomainDataSource」コントロールをドラッグする。
    (「DomainDataSource」自体はユーザーに何かしらを表示するコントロールではないのでデザイナー画面には表示されない。その昔、コンポーネントなどと呼ばれていた類のコントロール)
  3. 「DomainDataSource」のプロパティを以下のように設定し、「GetEmployeesQuery」によってデータを自動的に取得させる。
    1. <riaControls:DomainDataSource Name="employeeDataSource" QueryName="GetEmployeesQuery" AutoLoad="True" >
    2.     <riaControls:DomainDataSource.DomainContext>
    3.         <ds:MyContext/>
    4.     </riaControls:DomainDataSource.DomainContext>
  4. 「DataGrid」の「ItemsSource」に「DomainDataSource」コントロールの「Data」プロパティをバインディングする。
    1. <sdk:DataGrid AutoGenerateColumns="True" IsReadOnly="True" x:Name="dataGrid1" MinHeight="100" ItemsSource="{Binding Data, ElementName=employeeDataSource}" />

「DomainDataSource」に手動で読み込む

「DomainDataSource」には「AutoLoad」を「False」にして手動で読み込む方法も用意されているので、それを使ってみる。

  1. 「DomainDataSource」の「AutoLoad」を「False」にする。
  2. 「TextBlock」の次にデータロード用のボタンを追加する。
    「DomainDataSource」コントロールには予め「LoadCommand」が用意されているようなので、それを「Command」にバインドしてあげれば良さそうだ。
    1. <Button Width="100" HorizontalAlignment="Left" Content="Load" Command="{Binding LoadCommand, ElementName=employeeDataSource}"/>

「DomainDataSource」に抽出条件を指定する

「DomainDataSource」に画面から抽出条件を指定して表示できるようにする。

  1. 「RIA1.Web」プロジェクトの「MyService.cs」に以下の抽出メソッドを追加する。
    1. public IQueryable<Employees> GetEmployeesByCity(string cityname)
    2. {
    3.     return this.ObjectContext.Employees.Where(e => e.City == cityname);
    4. }
  2. 「RIA1」プロジェクトの「EmployeeList.xaml」のLoadボタンをStackPanelに入れ、抽出条件指定用のTextBlockを追加する。
    image
    1. <StackPanel Orientation="Horizontal">
    2.     <TextBlock Text="CityName : " />
    3.     <TextBox Name="txtCity" Width="100" Height="20"/>
    4.     <Button Width="100" HorizontalAlignment="Left" Content="Load" Command="{Binding LoadCommand, ElementName=employeeDataSource}"/>
    5. </StackPanel>

  3. 「DomainDataSource」コントロールに「QueryParameters」プロパティを追加し、上記の抽出条件指定用TextBlockとバインドする。
    1. <riaControls:DomainDataSource Name="employeeDataSource" QueryName="GetEmployeesByCityQuery" AutoLoad="False" >
    2.     <riaControls:DomainDataSource.DomainContext>
    3.         <ds:MyContext/>
    4.     </riaControls:DomainDataSource.DomainContext>
    5.     <riaControls:DomainDataSource.QueryParameters>
    6.         <riaControls:Parameter ParameterName="cityname" Value="{Binding Text, ElementName=txtCity}"/>
    7.     </riaControls:DomainDataSource.QueryParameters>
    8. </riaControls:DomainDataSource>
  4. これで実行し、抽出条件に「London」と入力して「Load」ボタンを押すと「London」のデータだけが表示される。
    image

「DomainDataSource」にソート条件を指定する

  1. 「DomainDataSource」には「SortDescriptors」属性を指定することによって簡単にソート条件を追加することができる。
    1. <riaControls:DomainDataSource Name="employeeDataSource" QueryName="GetEmployeesByCityQuery" AutoLoad="False" >
    2.     <riaControls:DomainDataSource.DomainContext>
    3.         <ds:MyContext/>
    4.     </riaControls:DomainDataSource.DomainContext>
    5.     <riaControls:DomainDataSource.QueryParameters>
    6.         <riaControls:Parameter ParameterName="cityname" Value="{Binding Text, ElementName=txtCity}"/>
    7.     </riaControls:DomainDataSource.QueryParameters>
    8.     <riaControls:DomainDataSource.SortDescriptors>
    9.         <riaControls:SortDescriptor PropertyPath="LastName" Direction="Ascending" />
    10.     </riaControls:DomainDataSource.SortDescriptors>
    11. </riaControls:DomainDataSource>
  2. ソート指定した項目は先頭カラムに表示される。
    image

「DomainDataSource」にページング処理を追加する

  1. 「DomainDataSource」のクエリーを「GetEmployeesQuery」に戻して、追加した「QueryParameters」を削除する。
  2. ツールボックスから「DataGrid」の下に「DataPager」コントロールをドロップし、XAMLを以下のように指定する。
    1. <sdk:DataPager Source="{Binding Data, ElementName=employeeDataSource}" PageSize="4" HorizontalAlignment="Left"/>
  3. これで実行して「EmployeeList」を表示させると4行ごとにページングされて表示されるのが判る。
    image

「DomainDataSource」にフィルターを追加する

「DomainDataSource」に抽出条件を指定する、ではサーバーに対して抽出処理をやり直したが、今度はクライアント側だけでフィルター処理を行う。

  1. 「DomainDataSource」に以下のように「FilterDescriptors」属性を追加する。
    1. <riaControls:DomainDataSource.FilterDescriptors>
    2.     <riaControls:FilterDescriptor
    3.          PropertyPath="City"
    4.          Operator="IsEqualTo"
    5.          IgnoredValue=""
    6.          Value="{Binding ElementName=txtCity, Path=Text}" >
    7.     </riaControls:FilterDescriptor>
    8. </riaControls:DomainDataSource.FilterDescriptors>
  2. 実行して「EmployeeList」を表示させる。
    image
  3. 「CityName」テキストボックスにフィルター対象の「City」を指定して「Load」ボタンを押すとフィルターされたデータが表示される。
    image

 

<マスタ詳細ビューを作る>

「EmployeeList」の一覧表示ができたので、次は一覧で選択したデータを詳細表示してみる。詳細表示には「Silverlith Toolkit」に含まれている「DataForm」コントロールを使用する。

「DataForm」コントロールの使い方は以下に簡単に纏めている。
MTG Blog: ◆DataFormコントロールを使ってみる

DataFormを追加するには

  1. 「RIA1」プロジェクトから「EmployeeList.xaml」を開く
  2. 「DataForm」用の名前空間を追加する
    1. xmlns:dataForm="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit"
  3. 「DataPager」コントロールの下に以下のXAMLを追加して「DataForm」コントロールを追加する。
       1: <dataForm:DataForm x:Name="dataForm1" Header="Employee Infomation" 
       2:                    AutoGenerateFields="True" HorizontalAlignment="Left" 
       3:                    AutoEdit="False" AutoCommit="True" Height="400" Width="800"
       4:                    CurrentItem="{Binding SelectedItem,ElementName=dataGrid1}" 
       5:                    Margin="0,12,0,0" />

  4. アプリケーションを実行し「EmployeeList」を表示したのちに一覧でデータを選択すると、その下の「DataForm」に詳細が表示される。
    image

<関連データを表示する>


OrderとOrder_Detailsテーブルを使って親子関係(集約)のあるデータを表示してみる。


関連テーブルのデータを表示するには



  1. 「RIA1」プロジェクトの「Views」フォルダーを右クリックして「追加」「新しい項目」をクリックする。
  2. 「Orders」という名前で「Silverlight」ページを追加する。
  3. 「Orders.xaml」を開く。
  4. <Grid>タグの間に以下のXAMLを追加する。





    1. <ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}" >

    2.     <StackPanel x:Name="ContentStackPanel" Style="{StaticResource ContentStackPanelStyle}">

    3.         <TextBlock Text="Orders" Style="{StaticResource HeaderTextStyle}"/>

    4.     </StackPanel>

    5. </ScrollViewer>





  5. 「MainPage.xaml」を開く。
  6. 「EmployeeList」のリンクの次に「Orders」ページへのリンクを追加する。





    1. <HyperlinkButton x:Name="Link5" Style="{StaticResource LinkStyle}" NavigateUri="/Orders" TargetName="ContentFrame" Content="Orders"/>

    2. <Rectangle x:Name="Divider4" Style="{StaticResource DividerStyle}"/>





  7. 「RIA1.Web」プロジェクトの「MyService.metadata.cs」を開く。
  8. 「OrdersMetadata」クラスの「Order_Details」プロパティに「Include」属性と「Composition」属性を追加する。
    (この属性により、Order_Detailsのコレクションもインスタンシングされるのかな)
  9. 「RIA1.Web」プロジェクトの「MyService.cs」を開く。
  10. 「GetOrders」メソッドを修正して、項番8のコレクションを作る元ネタ用に、関連する「Order_Details」も読み込む指定に変更する。





    1. public IQueryable<Orders> GetOrders()

    2. {

    3.     //return this.ObjectContext.Orders;

    4.     return this.ObjectContext.Orders.Include("Order_Details").OrderBy(p => p.OrderID);

    5. }





  11. 「Orders.xaml」を開く。
  12. 「データ」メニューの「データソースの表示」をクリックして「データソースウィンドウ」を開く。
  13. 「Orders」をデザイン画面にドラッグする。
    image
    「Orders」の列を含む「DataGrid」が表示される。
  14. 同様に、「Orders」のノードの中に含まれる「Order_Details」を「Orders」の「DataGrid」の下にドラッグする。
    image
    「Order_Details」の列を含む「DataGrid」が表示される。
  15. 追加された「DataGrid」の「Width」プロパティを削除し、画面の幅いっぱいに表示されるようにする。
  16. それぞれの「DataGrid」の前に「TextBlock」コントロールを追加して以下のようにラベルが表示されるようにする。


       1: <TextBlock Text="Order見出し" />

       1: <TextBlock Text="Order明細" />

    image


  17. 「DomainDataSource」にフィルターを追加して取得されるデータ数を制限しておく。


       1: <riaControls:DomainDataSource.FilterDescriptors>
       2:     <riaControls:FilterDescriptor PropertyPath="EmployeeID" Operator="IsLessThan" Value="5" />
       3: </riaControls:DomainDataSource.FilterDescriptors>

     



  18. アプリケーションを実行し、「Orders」を開く。

  19. 「Order見出し」の行を選択すると対応する明細データが「Order明細」に表示される。
    image


関連テーブルのデータを表示するには2


上記では「データソース」をドロップすることによって半自動的に画面デザインを行ったが、実装を確認する意味で中身を確認しながら手動で設定してみる。



  1. 「RIA1」プロジェクトの「Views」フォルダーを右クリックして「追加」「新しい項目」をクリックする。
  2. 「注文」という名前で「Silverlight」ページを追加する。
  3. 「注文.xaml」を開く。
  4. <Grid>タグの間に以下のXAMLを追加する。


       1: <StackPanel x:Name="ContentStackPanel" Style="{StaticResource ContentStackPanelStyle}">
       2:  
       3:     <TextBlock Text="注文" Style="{StaticResource HeaderTextStyle}"/>
       4: </StackPanel>

  5. 「MainPage.xaml」を開く。
  6. 「EmployeeList」のリンクの次に「注文」ページへのリンクを追加する。


       1: <HyperlinkButton x:Name="Link4" Style="{StaticResource LinkStyle}" NavigateUri="/注文" TargetName="ContentFrame" Content="注文"/>
       2:  
       3:  <Rectangle x:Name="Divider3" Style="{StaticResource DividerStyle}"/>

  7. 「注文.xaml」を開き「注文」タイトルの下に「注文タイトル」の「TextBlock」を追加


       1: <TextBlock Text="注文タイトル" />

  8. その下に「DtaGrid」を追加し、以下のように設定。


       1: <sdk:DataGrid x:Name="注文DataGrid" AutoGenerateColumns="True" ItemsSource="{Binding Data,ElementName=注文DomainDataSource}"  Height="200" IsReadOnly="True"/>

  9. その下に「注文明細」の「TextBlock」を追加


       1: <TextBlock Text="注文明細" />

  10. その下に「DataGrid」を追加し、以下のように設定。


       1: <sdk:DataGrid x:Name="注文明細DataGrid" AutoGenerateColumns="True" ItemsSource="{Binding Data.Order_Details, ElementName=注文DomainDataSource}"  Height="200" />

  11. これで実行して、「注文」ページを表示させると「Orders」ページとほぼ同様の表示となる。
    image


0 件のコメント:

コメントを投稿

私が最近チェックした記事