バージョン

igGrid を DataTable にバインディング

トピックの概要

目的

バージョン 12.2 以降、Ignite UI for MVC Grid では DataTable オブジェクトにバインドできるようになりました。このトピックでは、この機能を紹介し、Ignite UI for MVC の Grid と DataTable を構成し、使用する方法を説明します。また、グリッドの編集機能を併用した DataTable の利用方法も説明します。

前提条件

このトピックを理解するために、以下のトピックを参照することをお勧めします。

このトピックの内容

このトピックは、以下のセクションで構成されます。

概要

DataTable へのバインド

バージョン 12.2 以降、igGrid は ADO.NET DataTable とのバインディングをサポートしています。

DataTable とのバインディングは、GridDataSourceActionDataTable を渡し、ビューでグリッドを定義して実行します。

以下のシナリオのモデルは DataTable です (タイプは .NET dynamic に設定できます)。この場合、GridDataSourceAction ActionMethod から DataTable が返ります。このメソッドはモデル (DataTable) を JSON にシリアル化し、クライアントで消費するためそれをサーバーから返します。

Razor の場合:

@model  System.Data.DataTable
@(Html.Infragistics().Grid<System.Data.DataTable>().ID("grid1").Height("500px")
        …
        .DataSource(Model)
        .DataSourceUrl(Url.Action("UpdateDataTableGrid"))        
        .DataBind()        
        .Render()
)

C# の場合:

[GridDataSourceAction]
[ActionName("UpdateDataTableGrid")]
public ActionResult UpdateDataTableGrid()
{
    DataTable dt = this.MyEmployees;
    return View("UpdateDataTableGrid", dt);
}

AutoGenerateColumns プロパティが true に設定される場合、グリッドの列定義は DataTable 定義から取得されます。

注: 1 つ以上の列を定義して AutoGenerateColumnstrue に設定することは無効です。すべての列を定義するか、すべての列を自動的に生成する必要があります。

DataSet にバインド

igGrid には新しいプロパティ DataMember を導入しました。

このプロパティは、現在の igGrid にバインドされた DataSet から取得した DataTable の名前を保存します。

このプロパティを設定すると、グリッドは、DataSet から取得した DataMember 値と一致する DataTable の名前を検索して、それにグリッドをバインドします。AutoGenerateLayouts が false で、レイアウトを手動定義するときこのプロパティが便利です。

注: v12.2 では、AutogenerateLayouts がデフォルトで false になるように変更しました。

既知の問題と制限

フィルタリング、グルーピング、ソーティングの各機能にサポートしているのはローカル構成だけで、サマリーはサポートしていません。

igGrid は、リモート フィルタリング、ソーティング、グルーピングを実行するとき、内部で LINQ 式を使用してデータのフィルタリングやソーティングをします。DataTableDataSet をデータ ソースとして使用するとき、LINQ 式は機能しません。したがって、DataTableDataSet にバインドするとき、フィルタリング、並べ替え、グループ化の各機能を構成できる対象は、ローカル データだけです。

同じく、DataTable/DataSet をデータ ソースとして使用するとき、集計機能はサポートしていません。

Razor の場合:

@(Html.Infragistics().Grid<dynamic>().ID("grid1").Height("500px")
        .AutoGenerateColumns(true)       
        .RenderCheckboxes(true)
        .AutoCommit(false)       
        .Features(features => {
            features.Sorting().Type(OpType.Local).Mode(SortingMode.Single);
            features.Filtering().Type(OpType.Local);
            features.GroupBy().Type(OpType.Local);
            features.Paging().PageSize(5).Type(OpType.Remote);
            features.Updating();
            features.Hiding();
            features.Selection().Mode(SelectionMode.Row).MultipleSelection(true);
            features.RowSelectors();
            features.Resizing();
            features.Tooltips().Visibility(TooltipsVisibility.Always);
        })        
        .GenerateCompactJSONResponse(false)
        .DataSource(Model)
        .DataSourceUrl(Url.Action("datatable-interactions"))
        .UpdateUrl(Url.Action("EditingSaveChanges"))
        .DataBind()
        .Width("100%")
        .Height("100%")
        .Render()
)

リモートの並べ替えおよびフィルター処理は、要求を処理してから、データを返す前に DataSet/DataTable レベルでデータをフィルターするか、並べ替えることによって実現できます。

以下の例は、要求を処理し、データを返す前に DataTable レベルでデータの並べ替え、およびリモート並べ替えを実装する方法を紹介します。

C# の場合:

[GridDataSourceAction]
[ActionName("UpdateDataTableGrid")]
public ActionResult UpdateDataTableGrid()
{
    DataTable dt = this.MyEmployees;
    NameValueCollection queryString = HttpUtility.ParseQueryString(Request.QueryString.ToString());
    // check the query string for sorting expressions
    List<SortExpression> sortExpressions = BuildSortExpressions(queryString, "sort", true);
    DataView dv = customers.DefaultView;
    if (sortExpressions.Count > 0)
    {
        String sortExpression = "";
        foreach (SortExpression expr in sortExpressions)
        {
            sortExpression += expr.Key + " " + (expr.Mode == SortMode.Ascending ? "asc" : "desc") + ",";
        }
        dv.Sort = sortExpression.Substring(0, sortExpression.Length - 1);
    }
    return View("UpdateDataTableGrid", dv.ToTable());
}

public List<SortExpression> BuildSortExpressions(NameValueCollection queryString, string sortKey, bool isTable)
{
    List<SortExpression> expressions = new List<SortExpression>();
    List<string> sortKeys = new List<string>();
    foreach (string key in queryString.Keys)
    {
        if (!string.IsNullOrEmpty(key) && key.StartsWith(sortKey))
        {
            SortExpression e = new SortExpression();
            e.Key = key.Substring(key.IndexOf("(")).Replace("(", "").Replace(")", "");
            e.Logic = "AND";
            e.Mode = queryString[key].ToLower().StartsWith("asc") ? SortMode.Ascending : SortMode.Descending;
            expressions.Add(e);
            sortKeys.Add(key);
        }
    }
    if (sortKeys.Count > 0 && isTable)
    {
        foreach (string sortedKey in sortKeys)
        {
            queryString.Remove(sortedKey);
        }
        string url = Request.Url.AbsolutePath;
        string updatedQueryString = "?" + queryString.ToString();
        Response.Redirect(url + updatedQueryString);
    }
    return expressions;
}

以下の機能は DataTableDataSet にバインドするときリモートで機能します。

  • ページング
  • 更新 - LoadTransactions が機能するように変更してください。

DataTable や DataSet に PrimaryKey が設定されていない場合、Grid に明示的に設定してください。

DataTableDataSetPrimaryKey を定義しておくると、igGrid がそれを自動的に使用します。あるいは手動設定することもできます。更新機能を有効にしたとき、以上の設定が必要です。

Razor の場合:

// The Model in the code snippet below is a DataTable
@(Html.Infragistics().Grid<DataTable>(Model).ID("grid1").Height("500px")
        .PrimaryKey("ProductID")
        .AutoGenerateLayouts(true)
        .AutoGenerateColumns(true)       
        .RenderCheckboxes(true)
        .AutoCommit(false)   
        .GenerateCompactJSONResponse(false)
        .DataSource(Model)
        .DataSourceUrl(Url.Action("datatable-interactions"))
        .UpdateUrl(Url.Action("EditingSaveChanges"))
        .DataBind()
        .Width("100%")
        .Height("100%")
        .Render()
)

更新時は、Dictionary<string, string> をサポートするシリアライザーを使用してください。

更新時は、Dictionary<string, string> をサポートするシリアライザーを使用してください。ちなみに、Microsoft JSON シリアライザーでは Dictionary を JSON にシリアル化解除できないという問題があります。更新機能を使用するとき、GridModel で、LoadTransactions メソッドをオーバーライドしてください。これには、Json.NET シリアライザーで対応できます。このシリアライザーは以下のページでダウンロードできます。また ASP.NET MVC 4 にはデフォルト シリアライザーとして組み込まれています。

http://www.newtonsoft.com/json

C# の場合:

public List<Transaction<T>> LoadTransactionsDictionary<T>(string postdata) where T : class
{
    List<Transaction<T>> transactions = JsonConvert.DeserializeObject<List<Transaction<T>>>(postdata);
    return transactions;
}

もう 1 つ、テーブルのレイアウトを基にモデルを作成し、LoadTransactions メソッドで使用する方法があります。以下のサンプル コードで紹介しているのは、DataTable をバインドして、LoadTransactions メソッドでテーブル レイアウトを基にモデルを渡すときの更新機能の利用方法です。

C# の場合:

public class Employee
{
    public int EmployeeID { get; set; }
    public int DepartmentID { get; set; }
    public string Name { get; set; }
    public string Site { get; set; }
    public DateTime DateOfHire { get; set; }
    public bool OnSite { get; set; }
}
...

public ActionResult EditingSaveChanges()
{
    ViewData["GenerateCompactJSONResponse"] = false;
    GridModel m = new GridModel();
    List<Transaction<Employee>> transactions = m.LoadTransactions<Employee>(HttpContext.Request.Form["ig_transactions"]);
    foreach (Transaction<Employee> t in transactions)
    {
        if (t.type == "row")
        {
            DataRow dr = this.MyEmployees.Rows.Find(Int32.Parse(t.rowId));
            if (t.row.Name != null)
            {
                dr["Name"] = t.row.Name;
            }
            if (t.row.DateOfHire != null)
            {
                dr["DateOfHire"] = t.row.DateOfHire;
            }
            if (t.row.Site != null)
            {
                dr["Site"] = t.row.Site;
            }
            if (t.row.OnSite != null)
            {
                dr["OnSite"] = t.row.OnSite;
            }
            if (t.row.DepartmentID != null)
            {
                dr["DepartmentID"] = t.row.DepartmentID;
            }
            this.MyEmployees.AcceptChanges();
        }
    }
    JsonResult result = new JsonResult();
    Dictionary<string, bool> response = new Dictionary<string, bool>();
    response.Add("Success", true);
    result.Data = response;
    return result;
}

ビューに Ignite UI for MVC Grid の列を手動で作成します。

igGrid をビューに定義して、DataTable をグリッドのモデルとして使用すると、列は自動生成以外では生成できなくなります。列を手動で定義するときは、DataTable 構造に対応したモデルを定義し、それをグリッドのタイプに設定してください。

注: カスタム タイプ Employee のフィールドでは、そのフィールドが表す DataTableDataColumns のタイプとキーを一致させてください。

C# の場合:

DataTable dtData = new DataTable("Employees");
dtData.Columns.Add("EmployeeID", typeof(int));
dtData.Columns.Add("Name", typeof(string));
dtData.Columns.Add("OnSite", typeof(bool));
dtData.Columns.Add("DateOfHire", typeof(DateTime));
dtData.Columns.Add("DepartmentID", typeof(int));
dtData.Columns.Add("Site", typeof(string));

C# の場合:

public class Employee
{
    public int EmployeeID { get; set; }
    public int DepartmentID { get; set; }
    public string Name { get; set; }
    public string Site { get; set; }
    public DateTime DateOfHire { get; set; }
    public bool OnSite { get; set; }
}

Razor の場合:

@( Html.Infragistics().Grid<Employee>().ID("grid1").Height("500px").Width("1000px")
        .Columns(column =>
        {
            column.For(x => x.EmployeeID).DataType("number").HeaderText("Employee ID");
            column.For(x => x.Name).DataType("string").HeaderText("Name");
            column.For(x => x.Site).DataType("string").HeaderText("Site");
            column.For(x => x.DepartmentID).DataType("number").HeaderText("Department");
            column.For(x => x.DateOfHire).DataType("date").HeaderText("Date Of Hire");
            column.For(x => x.OnSite).DataType("bool").HeaderText("On site");
        })   
        .DataBind()
        .Render()
)

Json.NET シリアライザーによるグリッドの更新

この手順では、DataTable とバインドした間にグリッドの更新機能を使用するときの LoadTransaction メソッドの実装方法を説明します。

前提条件

この手順を実行するには、以下のリソースが必要です。

  • 必要な Ignite UI for jQuery の JavaScript と CSS ファイル
  • Infragistics.Web.Mvc.dll アセンブリへの参照
  • Json.NET シリアライザー - Newtonsoft.Json.dll

これは、http://www.newtonsoft.com/json からダウンロードできます。

概要

以下はプロセスの概念的概要です。

  1. DataTable を GridDataSourceAction で渡す
  2. Json.NET ライブラリをプロジェクトに追加し、参照情報を設定する
  3. LoadTransactionsDictionary メソッドを実装する
  4. JSON 要求から日付を解析する

手順

以下に示したのは、igGridDataTable にバインドするときの更新機能を有効にする一般的な手順概要です。

  1. DataTable を GridDataSourceAction で渡す

    1. DataTableDataSourceUrl アクションで渡し、DataTable をグリッドのモデルとして設定します。
    2. また、UpdateUrlEditingSaveChanges コントローラー アクションに設定します。このアクションは、LINQ の間、変更結果をデータベースで維持します。

      Razor の場合:

      @(Html.Infragistics().Grid<DataTable>(Model).ID("grid1").Height("500px")
      .AutoGenerateColumns(true)       
      .RenderCheckboxes(true)
      .AutoCommit(false)       
      .Features(features => {
          features.Sorting().Type(OpType.Local).Mode(SortingMode.Single);
          features.Filtering().Type(OpType.Local);
          features.GroupBy().Type(OpType.Local);
          features.Paging().PageSize(5).Type(OpType.Remote);
          features.Updating();
          features.Hiding();
          features.Selection().Mode(SelectionMode.Row).MultipleSelection(true);
          features.RowSelectors();
          features.Resizing();
          features.Tooltips().Visibility(TooltipsVisibility.Always);
      })        
      .GenerateCompactJSONResponse(false)
      .DataSource(Model)
      .DataSourceUrl(Url.Action("DataTableInteractions"))
      .UpdateUrl(Url.Action("EditingSaveChanges"))
      .DataBind()
      .Width("100%")
      .Height("100%")
      .Render()
      )
      

      C# の場合:

      public ActionResult DataTableInteractions()
      { 
      
      DataTable dt = this.MyEmployees;  
      return View("DataTableInteractions",dt);
      }
      
  2. Json.NET ライブラリをプロジェクトに追加し、参照情報を設定する

    1. Newtonsoft.Json.dll をダウンロードする

      http://www.newtonsoft.com/json

      この dll は ASP.NET MVC 3 以下に必要ですが、デフォルトの ASP.NET MVC 4 テンプレートに組み込まれています。この JSON ライブラリは NuGet でも取得できます。

    2. プロジェクトの参照としてアセンブリー ファイルを追加
  3. 新しいシリアライザーを使用するため、 LoadTransactionsDictionary メソッドを実装します。

    1. 新しいシリアライザーを使用するため、 LoadTransactionsDictionary メソッドを実装します。
    2. GridModel を継承する新しいクラスを作成します。
    3. LoadTransactionsDictionary メソッドを実装します。

      C# の場合:

      using Newtonsoft.Json;
      public class NewtonSoftGridModel : GridModel
      {
      /// <summary>
      /// loads a list of transactions from the POST data, in case saveChanges() is invoked in the client side and UpdateUrl is set
      /// to a valid controller action (GridUpdating)
      /// The method is using the Newtonsoft serializer, which gives the ability to deserialize objects in to Dictionary<string, string>
      /// </summary>
      /// <typeparam name="T"></typeparam>
      /// <param name="postdata"></param>
      /// <returns></returns>
      public List<Transaction<T>> LoadTransactionsDictionary<T>(string postdata) where T : class
      {
          List<Transaction<T>> transactions = JsonConvert.DeserializeObject<List<Transaction<T>>>(postdata);
          return transactions;
      }
      }
      
  4. JSON フォーマットから日付を解析する

    1. JSON 日付文字列を DateTime オブジェクトに変換します。
    2. ActionMethod は、グリッドからのデータ変更を保持する Ajax ポストを受け入れます。
    3. データ層の処理時には、ig_transactions というラベルのフォーム フィールドでグリッドのトランザクションを使用できます。
    4. 日付 は JSON フォーマットで受け取って DateTime に変換します。

      C# の場合:

      [ActionName("EditingSaveChanges")]
      public ActionResult EditingSaveChanges()
      {           DataTable dt = this.MyEmployees as DataTable;
      NewtonSoftGridModel m = new NewtonSoftGridModel();     
      
      List<Transaction<Dictionary<string, string>>> transactionsDict = m.LoadTransactionsDictionary<Dictionary<string, string>>(HttpContext.Request.Form["ig_transactions"]);
      foreach (Transaction<Dictionary<string, string>> t in transactionsDict)
      {…..
        if (t.type == "row")
          {
              DataRow dr =    dt.Rows.Find(Int32.Parse(t.rowId));
              if (t.row["Name"] != null)
              {
                  dr["Name"] = t.row["Name"];
              }
              if (t.row["DateOfHire"] != null)
              {
                  String dateString = t.row["DateOfHire"];
                  dateString = dateString.Replace("/Date(", "");
                  dateString = dateString.Replace(")/", "");
                  long lngString = Int64.Parse(dateString);
                  DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
                  DateTime dateValue = origin.AddSeconds(lngString / 1000);
                  dr["DateOfHire"] = dateValue;
              }
              if (t.row["Site"] != null)
              {
                  dr["Site"] = t.row["Site"];
              }
              if (t.row["OnSite"] != null)
              {
                  dr["OnSite"] = Boolean.Parse(t.row["OnSite"]);
              }
              if (t.row["DepartmentID"] != null)
              {
                  dr["DepartmentID"] = Int32.Parse(t.row["DepartmentID"]);
              }
              dt.AcceptChanges();
          }
      } 
      JsonResult result = new JsonResult();
      Dictionary<string, bool> response = new Dictionary<string, bool>();
      response.Add("Success", true);
      result.Data = response;
      return result;
      }
      

関連コンテンツ

トピック

このトピックの追加情報については、以下のトピックも合わせてご参照ください。

リソース

以下の資料 (Infragistics のコンテンツ ファミリー以外でもご利用いただけます) は、このトピックに関連する追加情報を提供します。

オンラインで表示: GitHub