バージョン 12.2 以降、Ignite UI for MVC Grid では DataTable
オブジェクトにバインドできるようになりました。このトピックでは、この機能を紹介し、Ignite UI for MVC の Grid と DataTable
を構成し、使用する方法を説明します。また、グリッドの編集機能を併用した DataTable
の利用方法も説明します。
このトピックを理解するために、以下のトピックを参照することをお勧めします。
igGrid の概要: このトピックでは、igGrid
を Web ページに追加する方法を説明します。
igGrid/igDataSource アーキテクチャの概要: このトピックでは、igGrid
内部の働きと、各種データ ソースとのバインディングを可能にするために igGrid がgDataSource
とどのように協調するかを説明します。
igGrid の更新: このトピックでは、igGrid
コントロールの更新機能の使用方法を説明します。
igGrid を使用する ASP.NET MVC アプリケーションの開発: このトピックでは、ASP.NET MVC アプリケーションで igGrid
を使用する方法を説明します。
このトピックは、以下のセクションで構成されます。
バージョン 12.2 以降、igGrid
は ADO.NET DataTable
とのバインディングをサポートしています。
DataTable
とのバインディングは、GridDataSourceAction
で DataTable
を渡し、ビューでグリッドを定義して実行します。
以下のシナリオのモデルは 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 つ以上の列を定義して
AutoGenerateColumns
を true に設定することは無効です。すべての列を定義するか、すべての列を自動的に生成する必要があります。
igGrid
には新しいプロパティ DataMember
を導入しました。
このプロパティは、現在の igGrid
にバインドされた DataSet
から取得した DataTable
の名前を保存します。
このプロパティを設定すると、グリッドは、DataSet
から取得した DataMember
値と一致する DataTable
の名前を検索して、それにグリッドをバインドします。AutoGenerateLayouts
が false で、レイアウトを手動定義するときこのプロパティが便利です。
注: v12.2 では、
AutogenerateLayouts
がデフォルトで false になるように変更しました。
igGrid
は、リモート フィルタリング、ソーティング、グルーピングを実行するとき、内部で LINQ 式を使用してデータのフィルタリングやソーティングをします。DataTable
や DataSet
をデータ ソースとして使用するとき、LINQ 式は機能しません。したがって、DataTable
や DataSet
にバインドするとき、フィルタリング、並べ替え、グループ化の各機能を構成できる対象は、ローカル データだけです。
同じく、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;
}
以下の機能は DataTable
や DataSet
にバインドするときリモートで機能します。
LoadTransactions
が機能するように変更してください。DataTable
や DataSet
に PrimaryKey
を定義しておくると、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>
をサポートするシリアライザーを使用してください。ちなみに、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;
}
igGrid
をビューに定義して、DataTable
をグリッドのモデルとして使用すると、列は自動生成以外では生成できなくなります。列を手動で定義するときは、DataTable
構造に対応したモデルを定義し、それをグリッドのタイプに設定してください。
注: カスタム タイプ Employee のフィールドでは、そのフィールドが表す
DataTable
のDataColumns
のタイプとキーを一致させてください。
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()
)
この手順では、DataTable
とバインドした間にグリッドの更新機能を使用するときの LoadTransaction
メソッドの実装方法を説明します。
この手順を実行するには、以下のリソースが必要です。
これは、http://www.newtonsoft.com/json からダウンロードできます。
以下はプロセスの概念的概要です。
以下に示したのは、igGrid
を DataTable
にバインドするときの更新機能を有効にする一般的な手順概要です。
DataTable を GridDataSourceAction で渡す
DataTable
を DataSourceUrl
アクションで渡し、DataTable
をグリッドのモデルとして設定します。また、UpdateUrl
を EditingSaveChanges
コントローラー アクションに設定します。このアクションは、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);
}
Json.NET ライブラリをプロジェクトに追加し、参照情報を設定する
Newtonsoft.Json.dll をダウンロードする
http://www.newtonsoft.com/json
この dll は ASP.NET MVC 3 以下に必要ですが、デフォルトの ASP.NET MVC 4 テンプレートに組み込まれています。この JSON ライブラリは NuGet でも取得できます。
新しいシリアライザーを使用するため、 LoadTransactionsDictionary メソッドを実装します。
LoadTransactionsDictionary
メソッドを実装します。GridModel
を継承する新しいクラスを作成します。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;
}
}
DateTime
オブジェクトに変換します。ActionMethod
は、グリッドからのデータ変更を保持する Ajax ポストを受け入れます。ig_transactions
というラベルのフォーム フィールドでグリッドのトランザクションを使用できます。日付 は 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;
}
このトピックの追加情報については、以下のトピックも合わせてご参照ください。
igHierarchicalGrid
™ コントロールを構成して DataSet
にバインドする方法を紹介します。以下の資料 (Infragistics のコンテンツ ファミリー以外でもご利用いただけます) は、このトピックに関連する追加情報を提供します。
オンラインで表示: GitHub