轉載請註明作者及出處,謝謝
最近學習ASP.NET MVC 3,今天想試試jqGrid的TreeGrid模式,本以為跟著Demo一小會就能出效果,不料一直到晚上才搞定。於是把解決方案發出來以便剛接觸jqGrid的兄弟參考。
需求:
顯示樹狀結構的資料,如:部門列表。
@section head{ <script type="text/javascript"> $(function () { $('#treegrid').jqGrid({ treeGrid: true, treeGridModel: 'adjacency', ExpandColumn: 'DeptName', url: '/Department/Query/', datatype: 'json', mtype: 'GET', colNames: ['ID', '部門名稱', 'ParentID', '主管', '主管職代', '說明', 'VisibilityValue'], colModel: [ { name: 'ID', index: 'ID', hidden: true, width: 1, key: true }, { name: 'DeptName', index: 'DeptName', width: 180 }, { name: 'ParentID', index: 'ParentID', hidden: true, width: 1 }, { name: 'Director', index: 'Director', width: 200, align: 'left' }, { name: 'DeputyID', index: 'DeputyID', width: 200 }, { name: 'Summary', index: 'Summary', width: 200 }, { name: 'VisibilityValue', index: 'VisibilityValue', hidden: true, width: 1 } ], pager: '#ptreegrid', height: 'auto' }); }) </script>}
小小的補充下,我使用Razor視圖引擎,所以這一部分是視圖裡面定義javascript的Sectiion。個人感覺,除了不能“所見即所得 (WYSIWYG)”之外,這個引擎比傳統的ASPX要好,但具體好在什麼地方呢,也說不上來,感覺而已(不要敲我:))
今天有三分之一的時間花在一個小失誤上,在上面的這段代碼中,datatype被我寫成了dataType,結果花了n小時,一個字一個字的找出來...
使用jqGrid TreeGrid,上面這些代碼就足夠了,設定還有多餘的,比如pager不是必須的。
再小小的一段題外話,為什麼網上的很多例子在使用jqGrid時使用的mtype為"POST"?,從RESTful的角度來說不應該是"GET"嗎?莫非違背RESTful原則使用MVC比較有快感?
非常重要的工作是:必須把grid.treegrid.js引用進頁面,我一直以為有那個jquery.jqGrid.min.js就夠了,結果還是在加入了grid.treegrid.js後才能在點擊一行後進入Controller。
剩下就是Controller裡面的內容了。
public ActionResult Query(Guid? nodeid, int? n_level) { Guid? deptID = nodeid; int level = n_level != null ? (int)n_level + 1 : 0; JsonResult json = new JsonResult(); json.JsonRequestBehavior = JsonRequestBehavior.AllowGet; var deptMng = new DeptManager(); var depts = deptMng.GetChild(deptID, true); json.Data = new { page = 1, total = 1, records = depts.Count, rows = (from dept in depts select new { cell = new[] { dept.ID.ToString(), dept.DeptName, dept.ParentID != null ? dept.ParentID.ToString() : "", dept.DirectorID != null ? dept.DirectorID.ToString() : "", dept.Deputy != null ? dept.Deputy.ToString() : "", dept.Summary != null ? dept.Summary : "", dept.VisibilityValue.ToString(), level.ToString(), deptID != null ? deptID.ToString() : string.Empty, deptMng.GetChild(dept.ID,true).Count == 0 ? "true":"false", "false" } }) }; return json; }
說句實話,我灰常灰常喜歡”約定優於配置"這句話,很多時侯,背上的包袱總是自已加上去的,因此,為什麼使用nodeid和n_level這兩個參數名,我想還沒有明白的就不用深究了,如果你想使用jqGrid的TreeGrid,那麼你就使用這個參數列表吧。
當第一次載入視圖時,nodeid和n_level均為空白,因為你還沒有點擊樹的任一節點,所以它哥倆預設為null。
當n_level為空白時level為0,否則level = n_level + 1,為什麼這樣,後面提到。
deptMng.GetChild方法為擷取指定部門ID的下一級子部門,不包括下二級。
ok,來到關鍵的地方了,json.Data裡面放的匿名對象中,前三個成員比較簡單,在能找到的所有的例子中,page和total都是1,所以我也就沒有多想,名堂全在rows對象裡面了:
先把你colNames和colModel裡面需要的資料準備好,在本例中我使用了7個欄位(真不明白,一個測試程式幹嘛型那麼多欄位),從第八個開始有講究:
level.ToString(),代表當前這行資料處於第level層,這也就是我為什麼前面使用n_level+1的原因了,如果n_level為空白的話,將要顯示第0層,如果其不為空白,說明當前level是n_level,將要顯示的下一層level當然是n_level+1了。
第九個欄位疑似儲存父部門ID的,為什麼是疑似呢,因為時間原因我還沒有弄深入...(2011.9.11更新:可以肯定的是,這個欄位就是儲存父部門ID的,而且很重要的一點是,如果某節點的父ID為空白的話,一定得使用null或是"null"來代替,而不能使用"",為啥呢?除非你不想使用排序(sorting)功能了)
第10個欄位可以肯定的說,是存該部門是否包含子部門,記住:true代表沒有子部門,false代表有子部門,似乎應該說成是否不存在子部門。
第11個欄位,給個false就行了,原因不明...(2011.9.11更新: 這個欄位的含義為:顯示資料是否展開,true為展開,false為收合)
效果出來了。
剛開始使用jqGrid,很多東西還沒有搞明白,只能依葫蘆畫瓢,見笑了:)
2011.9.11更新-----------------------
在這裡有一個可以排序的例子,這裡是關於排序問題的解決方案,這兩個地址在說同一件事情。
這是有關TreeGrid的完整格式的範例:
{id: "1", name: "Cash", num: "100", debit: "400.00", credit: "250.00", balance: "150.00", enbl: "1", level: "0", parent: "null", isLeaf: false, expanded: false, loaded: true}
從level屬性之前,是和業務有關的資料,之後,就是jqgrid的TreeGrid所需的資料了,基本上從屬性名稱就可以看出作用。
一直在納悶,官方文檔到底在啥地方呢...
//2011.9.26應觀眾要求,做一個簡單的樣本吧
請點這裡下載