locked
WCF RIA サービスを使って、Silverlight の DataGridに列を抽出して表示させたい RRS feed

  • 質問

  • 初めて質問させていただきます。どうぞよろしくお願いします。

    SilverlightのDataGrid上に、SQL Serverのテーブルから列を抽出して表示させたいのですが、何も表示できない、またはエラーになってしまいます。
    以下に試行錯誤の過程をお示ししますので、どうぞご教授ください。
    また、途中の認識におかしな点がございましたら、指摘していただけると助かります。

    環境:
    OS: Windows 7
    IDE : Visual Studio 2010 SP1
    DB : SQL Server 2008 R2

    作成したプロジェクト:Silverlight アプリケーション(SilverlightApplication15)
    WCF RIA サービス:有効
    Silverlight バージョン : Silverlight 4

    追加した項目:
    ADO.net Entity Data Model(SalesCheckDataModel.edmx)をSilverlightApplication15.Webプロジェクトに追加
    ドメインサービスクラス(SalesCheckDomainService.cs)をSilverlightApplication15.Webプロジェクトに追加
    使用できるDataContext / ObjectContextクラスに、SalesCheckDataModel.edmxを指定
    表示されているテーブルをすべて「編集の有効化」にチェックを入れ、[メタデータ用の関連クラスを生成する]にもチェック

    読み込んだテーブル:
    テーブル名:M_ClientStaffTable
    clientCode VARCHAR(7)
    clientStaffCode : VARCHAR(3)
    clientStaffName VARCHAR(40)
    clientTel VARCHAR(13)



    できたこと:
    ・テーブルのすべての列をDataGridに表示する(Where句などで行の抽出はできました)

    やりたいこと:
    ・テーブルの列を抽出してDataGrid表示
    SELECT clientStaffName, clientTel
    FROM M_ClientStaffTable
    WHERE clientCode = '0000001';
    

    というようなSQLに該当すること

     

    下記は、列全表示ができた際のコードです。(手元に実際に作ったコードがない状態で書いているので、間違っていたらごめんなさい)

    //MainPage.xaml

      <Grid x:Name="LayoutRoot" Background="White">
        <StackPanel Orientation="Vertical">
          <Button x:Name="Button1" Content="データグリッドに表示" Click="Button1_Click" />
          <sdk:DataGrid Name="DataGrid01" />
        </StackPanel>
      </Grid>
    


    //MainPage.xaml.cs

    namespace SilverlightApplication15
    {
      public partial class MainPage : UserControl
      {
        public MainPage()
        {
          InitializeComponent();
        }
    
        // データグリッドに表示ボタン
        private void Button1_Click(object sender, RoutedEventArgs e)
        {
          // DomainContextの作成
          SalesCheckDomainContext dc = new SalesCheckDomainContext();
    
          // LINQの発行
          var records = from cs in dc.GetM_ClientStaffTableQuery()
                 where cs.clientCode = "0000001"
                 select cs;
          LoadOperation<M_ClientStaffTable> loadOp = dc.Load(records);
    
          //DataGridに表示
          DataGrid01.ItemsSource = loadOp.Entities;
        }
      }
    }
    


    試したこと:
    1. select句を変えた
    //MainPage.xaml.cs

    // データグリッドに表示ボタン
        private void Button1_Click(object sender, RoutedEventArgs e)
        {
          // DomainContextの作成
          SalesCheckDomainContext dc = new SalesCheckDomainContext();
    
          // LINQの発行
          var records = from cs in dc.GetM_ClientStaffTableQuery()
                 where cs.clientCode = "0000001"
                 select new { cs.clientStaffName, cs.clientTel };
          LoadOperation<M_ClientStaffTable> loadOp = dc.Load(records);
    
          //DataGridに表示
          DataGrid01.ItemsSource = loadOp.Entities;
        }
    

    これは、recordsがIQueryable<M_ClientStaffTable>型でなくなってしまうので、ダメだとコンパイラに怒られてしまいました。
    (手元に環境がないので、正確なエラー文でなくてごめんなさい)

    2.DomainContextからもらう型を、IQueryable<T>からIEnumerable<T>に変えた
    //MainPage.xaml.cs

        // データグリッドに表示ボタン
        private void Button1_Click(object sender, RoutedEventArgs e)
        {
          // DomainContextの作成
          SalesCheckDomainContext dc = new SalesCheckDomainContext();
    
          // LINQの発行
          var records = from cs in dc.M_ClientStaffTable
                 where cs.clientCode = "0000001"
                 select new { cs.clientStaffName, cs.clientTel };
          var recordList = records.ToList();
          foreach( r in records)
          {
            recordList.Add(r);
          }
    
          //DataGridに表示
          DataGrid01.ItemsSource = recordList;
        }
    


    これは、ビルドは通ったものの、列名のみDataGridに表示されるのみで、1列も表示されませんでした。
    recordListに変換しているのは、「LINQはforeach文で使われることが前提であり、foreach文のときに実行される」という記事を読んだためです。
    ステップ実行してみて、dc.ClientStaffTableを読み込んだ時点でそもそも1行もレコードが入っていなかったことが原因だということがわかりました。(クライアント側では実行できない?)

    3.ドメインサービスクラスで列を抽出した新しいメソッドを作る
    //SalesCheckDomainSerice.cs

      // TODO: アプリケーション ロジックを含むメソッドを作成します。
      [EnableClientAccess()]
      public class SalesCheckDomainService : DomainService
      {
        public IQueryable<M_ClientStaffTable> GetM_ClientStaffTableLimitted()
        {
          return
            (
              var records = from cs in this.ObjectContext.M_ClientStaffTable
                     where cs.clientCode = "0000001"
                     select new { cs.clientStaffName, cs.clientTel }
            );
        }
    }
    

    これは、1と同様のエラーがでました(当然でした)

    4.列を絞ったテーブルを格納するクラスを作成し、ドメインサービスに新しいメソッドを作る
    //SalesCheckDomainSerice.cs

      // TODO: アプリケーション ロジックを含むメソッドを作成します。
      [EnableClientAccess()]
      public class SalesCheckDomainService : DomainService
      {
        public IQueryable<LimittedClientStaff> GetM_ClientStaffTableLimitted()
        {
          return
            (
              var records = from cs in this.ObjectContext.M_ClientStaffTable
                     where cs.clientCode = "0000001"
                     select new LimittedClientStaff(){clientStaffName = cs.clientStaffName, clientTel = cs.clientTel }
            );
        }
      }
    
      public class LimittedClientStaff
      {
        public string clientStaffName;
        public string clientTel;
      }
    }
    

    これは、ビルドは通ったものの、クライアントから呼び出せませんでした(SalesCheckDomainContextのインテリセンスに出てこなかった)


    質問したい点は次の2点です。
    Q1.表題とおり、SilverlightのDataGridに、列を抽出したテーブルを表示するには、どうしたらよいでしょうか
    Q2.DomainService.csに書いたメソッドを、クライアントに利用させる(DomainContextに認識させる?)にはどうしたらよいでしょうか

    非常に長く読みにくい文章になってしまったことを謝罪します。どうかよろしくお願いします。

    2011年7月18日 16:53

回答

  • ご回答ありがとうございました。

    自己解決しました。
    MainPage.xaml上で、DataGrid列の自動作成をOFFにし、表示させたい列をDataColumnにバインドすることによって、欲しかった表示をさせることができました。

    //MainPage.xaml
      <Grid x:Name="LayoutRoot" Background="White">
        <StackPanel Orientation="Vertical" Name="stackpanel01">
          <Button Content="データグリッドを表示" Name="Button1" Click="Button1_Click" />
          <sdk:DataGrid Name="DataGrid01" AutoGenerateColumns="False">
            <sdk:DataGrid.Columns>
              <sdk:DataGridTextColumn Header="ClientStaffName"
                          Binding="{Binding clientStaffName}"
                          />
              <sdk:DataGridTextColumn Header="ClientTel"
                          Binding="{Binding clientTel}"
                          />
            </sdk:DataGrid.Columns>
          </sdk:DataGrid>
        </StackPanel>
      </Grid>
    


    //MainPage.xaml.cs

    namespace SilverlightApplication15
    {
      public partial class MainPage : UserControl
      {
        public MainPage()
        {
          InitializeComponent();
        }
    
        // データグリッドを表示ボタン
        private void Button1_Click(object sender, RoutedEventArgs e)
        {
          // domain context の作成(DomainServiceの作成時に自動生成されたもの)
          // Silverlight15.Web名前空間内
          SalesCheckDataDomainContext dc = new SalesCheckDataDomainContext();
    
          // LINQ の設定
          var records = from cs in dc.GetM_ClientStaffTableQuery()
                 where cs.clientCode == "0000001"
                 select cs;
    
          // LINQ の 実行
          LoadOperation loadOp = dc.Load(records);
    
          // DataGridに表示
          DataGrid01.ItemsSource = loadOp.Entities;
        }
      }
    }
    

    ありがとうございました。

    2011年7月19日 2:01

すべての返信

  • 他に方法はあると思いますが。
    とりあえず選択したものだけ表示できればよい、ということならDataGridにすべてを任せるのではなく、その中に表示したい項目だけ表示するようにコントロールを設定してしまうのが楽なよーな。。。


    あおい情報システム株式会社 小野修司(どっとねっとふぁん)
    2011年7月19日 1:02
  • ご回答ありがとうございました。

    自己解決しました。
    MainPage.xaml上で、DataGrid列の自動作成をOFFにし、表示させたい列をDataColumnにバインドすることによって、欲しかった表示をさせることができました。

    //MainPage.xaml
      <Grid x:Name="LayoutRoot" Background="White">
        <StackPanel Orientation="Vertical" Name="stackpanel01">
          <Button Content="データグリッドを表示" Name="Button1" Click="Button1_Click" />
          <sdk:DataGrid Name="DataGrid01" AutoGenerateColumns="False">
            <sdk:DataGrid.Columns>
              <sdk:DataGridTextColumn Header="ClientStaffName"
                          Binding="{Binding clientStaffName}"
                          />
              <sdk:DataGridTextColumn Header="ClientTel"
                          Binding="{Binding clientTel}"
                          />
            </sdk:DataGrid.Columns>
          </sdk:DataGrid>
        </StackPanel>
      </Grid>
    


    //MainPage.xaml.cs

    namespace SilverlightApplication15
    {
      public partial class MainPage : UserControl
      {
        public MainPage()
        {
          InitializeComponent();
        }
    
        // データグリッドを表示ボタン
        private void Button1_Click(object sender, RoutedEventArgs e)
        {
          // domain context の作成(DomainServiceの作成時に自動生成されたもの)
          // Silverlight15.Web名前空間内
          SalesCheckDataDomainContext dc = new SalesCheckDataDomainContext();
    
          // LINQ の設定
          var records = from cs in dc.GetM_ClientStaffTableQuery()
                 where cs.clientCode == "0000001"
                 select cs;
    
          // LINQ の 実行
          LoadOperation loadOp = dc.Load(records);
    
          // DataGridに表示
          DataGrid01.ItemsSource = loadOp.Entities;
        }
      }
    }
    

    ありがとうございました。

    2011年7月19日 2:01