これはうまくいきます! ..しかし、まだもう1つ必要です...
さて、これは「コメント」と質問の両方です。 1つ目は、asp.net webmethod/jqGridアプローチの検索で他の人を助ける可能性のある実用的な例です。以下のコードは、jqGridとの間でJSONパラメータを送受信するために完全に機能し、LINQを利用した正しいページング、並べ替え、フィルタリング(単一検索のみ)を実現します。
第二に、私の質問です:分離コードに送信される動的演算子を説明する適切な方法を誰かが決定しましたか?クライアントは「eq」を送信できる可能性があるため(等しい)、 "cn"(含む) "gt"(より大)、 "="または "<>"でwhereclause文字列を作成するだけでなく、whereclauseを動的に生成するより良い方法が必要です。むしろ、.Containsや.EndsWithなどを利用するDynamic Linqの機能と一緒にそれを含めることができます。
なんらかの述語ビルダー関数が必要になるかもしれません。
現在これを処理するコード(機能しますが、制限されています):
if (isSearch) {
searchOper = getOperator(searchOper); // need to associate correct operator to value sent from jqGrid
string whereClause = String.Format("{0} {1} {2}", searchField, searchOper, "@" + searchField);
//--- associate value to field parameter
Dictionary<string, object> param = new Dictionary<string, object>();
param.Add("@" + searchField, searchString);
query = query.Where(whereClause, new object[1] { param });
}
ショーで.........
==================================================
<script type="text/javascript">
$(document).ready(function() {
var grid = $("#grid");
$("#grid").jqGrid({
// setup custom parameter names to pass to server
prmNames: {
search: "isSearch",
nd: null,
rows: "numRows",
page: "page",
sort: "sortField",
order: "sortOrder"
},
// add by default to avoid webmethod parameter conflicts
postData: { searchString: '', searchField: '', searchOper: '' },
// setup ajax call to webmethod
datatype: function(postdata) {
$(".loading").show(); // make sure we can see loader text
$.ajax({
url: 'PageName.aspx/getGridData',
type: "POST",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(postdata),
dataType: "json",
success: function(data, st) {
if (st == "success") {
var grid = $("#grid")[0];
grid.addJSONData(JSON.parse(data.d));
}
},
error: function() {
alert("Error with AJAX callback");
}
});
},
// this is what jqGrid is looking for in json callback
jsonReader: {
root: "rows",
page: "page",
total: "totalpages",
records: "totalrecords",
cell: "cell",
id: "id", //index of the column with the PK in it
userdata: "userdata",
repeatitems: true
},
colNames: ['Id', 'First Name', 'Last Name'],
colModel: [
{ name: 'id', index: 'id', width: 55, search: false },
{ name: 'fname', index: 'fname', width: 200, searchoptions: { sopt: ['eq', 'ne', 'cn']} },
{ name: 'lname', index: 'lname', width: 200, searchoptions: { sopt: ['eq', 'ne', 'cn']} }
],
rowNum: 10,
rowList: [10, 20, 30],
pager: jQuery("#pager"),
sortname: "fname",
sortorder: "asc",
viewrecords: true,
caption: "Grid Title Here",
gridComplete: function() {
$(".loading").hide();
}
}).jqGrid('navGrid', '#pager', { edit: false, add: false, del: false },
{}, // default settings for edit
{}, // add
{}, // delete
{ closeOnEscape: true, closeAfterSearch: true}, //search
{}
)
});
</script>
==================================================
[WebMethod]
public static string getGridData(int? numRows, int? page, string sortField, string sortOrder, bool isSearch, string searchField, string searchString, string searchOper) {
string result = null;
MyDataContext db = null;
try {
//--- retrieve the data
db = new MyDataContext("my connection string path");
var query = from u in db.TBL_USERs
select new User {
id = u.REF_ID,
lname = u.LAST_NAME,
fname = u.FIRST_NAME
};
//--- determine if this is a search filter
if (isSearch) {
searchOper = getOperator(searchOper); // need to associate correct operator to value sent from jqGrid
string whereClause = String.Format("{0} {1} {2}", searchField, searchOper, "@" + searchField);
//--- associate value to field parameter
Dictionary<string, object> param = new Dictionary<string, object>();
param.Add("@" + searchField, searchString);
query = query.Where(whereClause, new object[1] { param });
}
//--- setup calculations
int pageIndex = page ?? 1; //--- current page
int pageSize = numRows ?? 10; //--- number of rows to show per page
int totalRecords = query.Count(); //--- number of total items from query
int totalPages = (int)Math.Ceiling((decimal)totalRecords / (decimal)pageSize); //--- number of pages
//--- filter dataset for paging and sorting
IQueryable<User> orderedRecords = query.OrderBy(sortfield);
IEnumerable<User> sortedRecords = orderedRecords.ToList();
if (sortorder == "desc") sortedRecords= sortedRecords.Reverse();
sortedRecords = sortedRecords
.Skip((pageIndex - 1) * pageSize) //--- page the data
.Take(pageSize);
//--- format json
var jsonData = new {
totalpages = totalPages, //--- number of pages
page = pageIndex, //--- current page
totalrecords = totalRecords, //--- total items
rows = (
from row in sortedRecords
select new {
i = row.id,
cell = new string[] {
row.id.ToString(), row.fname, row.lname
}
}
).ToArray()
};
result = Newtonsoft.Json.JsonConvert.SerializeObject(jsonData);
} catch (Exception ex) {
Debug.WriteLine(ex);
} finally {
if (db != null) db.Dispose();
}
return result;
}
/* === User Object =========================== */
public class User {
public int id { get; set; }
public string lname { get; set; }
public string fname { get; set; }
}
==================================================
LINQに動的なOrderBy句を含めるには、「Dynamic.cs」というAppCodeフォルダーにクラスをプルする必要がありました。 ここからダウンロードからファイルを取得できます。このファイルは「DynamicQuery」フォルダにあります。初期ロード以外ではどの列をフィルタリングするかわからないため、このファイルは動的なORDERBY句を利用する機能を提供します。
JSONをCシャープからJSにシリアル化するために、James Newton-King JSON.net DLL here here:http: //json.codeplex.com/releases/view/3781。ダウンロード後、「Newtonsoft.Json.Compact.dll」があり、これを参照としてBinフォルダーに追加できます
これは、システムを使用した私のUSINGのブロックです。 System.Collectionsを使用します。 System.Collections.Generic;を使用します。 System.Linqを使用します。 System.Web.UI.WebControlsを使用します。 System.Web.Servicesを使用します。 System.Linq.Dynamicを使用します。
JavaScriptの参照については、一部の人々を助けるために、次のスクリプトをそれぞれの順序で使用しています。1)jquery-1.3.2.min.js ... 2)jquery-ui-1.7.2.custom.min。 js ... 3)json.min.js ... 4)i18n/grid.locale-en.js ... 5)jquery.jqGrid.min.js
CSSには、jqGridの必需品とjQuery UIテーマを使用しています:1)jquery_theme/jquery-ui-1.7.2.custom.css ... 2)ui.jqgrid.css
バックエンドでシリアル化されていない文字列を解析したり、いくつかのJSロジックをセットアップしてパラメーターの数が異なるメソッドを切り替えたりすることなく、JSからWebMethodにパラメーターを取得するための鍵は、このブロックでした
postData: { searchString: '', searchField: '', searchOper: '' },
これらのパラメーターは、実際に検索を行っても正しく設定され、「リセット」するか、グリッドでフィルタリングを行わないようにすると、空にリセットされます。
これが他の人の役に立つことを願っています!!!!実行時に演算子を使用してwhereclauseを作成する動的なアプローチについて読んで返信する時間があれば、感謝します
文字列をMemberExpressionに変換する次の拡張メソッドを考えてみます。
public static class StringExtensions
{
public static MemberExpression ToMemberExpression(this string source, ParameterExpression p)
{
if (p == null)
throw new ArgumentNullException("p");
string[] properties = source.Split('.');
Expression expression = p;
Type type = p.Type;
foreach (var prop in properties)
{
var property = type.GetProperty(prop);
if (property == null)
throw new ArgumentException("Invalid expression", "source");
expression = Expression.MakeMemberAccess(expression, property);
type = property.PropertyType;
}
return (MemberExpression)expression;
}
}
以下のメソッドは、使用している文字列をLambda式に変換します。これを使用して、Linqクエリをフィルタリングできます。これは、Tをドメインエンティティとするジェネリックメソッドです。
public virtual Expression<Func<T, bool>> CreateExpression<T>(string searchField, string searchString, string searchOper)
{
Expression exp = null;
var p = Expression.Parameter(typeof(T), "p");
try
{
Expression propertyAccess = searchField.ToExpression(p);
switch (searchOper)
{
case "bw":
exp = Expression.Call(propertyAccess, typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) }), Expression.Constant(searchString));
break;
case "cn":
exp = Expression.Call(propertyAccess, typeof(string).GetMethod("Contains", new Type[] { typeof(string) }), Expression.Constant(searchString));
break;
case "ew":
exp = Expression.Call(propertyAccess, typeof(string).GetMethod("EndsWith", new Type[] { typeof(string) }), Expression.Constant(searchString));
break;
case "gt":
exp = Expression.GreaterThan(propertyAccess, Expression.Constant(searchString, propertyAccess.Type));
break;
case "ge":
exp = Expression.GreaterThanOrEqual(propertyAccess, Expression.Constant(searchString, propertyAccess.Type));
break;
case "lt":
exp = Expression.LessThan(propertyAccess, Expression.Constant(searchString, propertyAccess.Type));
break;
case "le":
exp = Expression.LessThanOrEqual(propertyAccess, Expression.Constant(searchString, propertyAccess.Type));
break;
case "eq":
exp = Expression.Equal(propertyAccess, Expression.Constant(searchString.ToType(propertyAccess.Type), propertyAccess.Type));
break;
case "ne":
exp = Expression.NotEqual(propertyAccess, Expression.Constant(searchString, propertyAccess.Type));
break;
default:
return null;
}
return (Expression<Func<T, bool>>)Expression.Lambda(exp, p);
}
catch
{
return null;
}
}
したがって、次のように使用できます。
db.TBL_USERs.Where(CreateExpression<TBL_USER>("LAST_NAME", "Costa", "eq"));
この記事 のぞき見を与える。 MVCでのjqgridの使用に焦点を当てていますが、関連情報を抽出できます。