2013年8月28日 星期三

ASP.NET MVC 4 + jQuery EasyUI Tree and TreeGrid

在今年七月時有發了兩篇關於無限階層樹狀選單的文章:

ASP.NET MVC + jQuery Easy UI Tree 無限階層的樹狀選單
ASP.NET MVC + jQuery Easy UI Tree 無限階層的樹狀選單 - 使用 JSON

第一篇說明如何在 ASP.NET MVC 的 View 裡使用 Razor Page Helper 建立遞迴顯示樹狀節點的 Tree 清單內容,然後再套用 jQuery EasyUI Tree,讓頁面上的清單轉換為樹狀選單。

第二篇則是進階的內容,分別說明如何在前端接收 JSON 資料然後產生樹狀選單,另一個則是說明非同步載入樹狀選單節點內容的作法。

這兩篇都是在說明如何去顯示既有的階層資料然後套用 jQuery Easy UI Tree 來顯示為樹狀選單,然而階層資料的維護管理功能則是隻字未提,這也不是要賣關子或是留一手,而是這個管理功能說起來也算是有些複雜,一直推敲琢磨該用什麼方式來說明會比較好,所以一直延宕至今。

因為也不是什麼多麼稀奇古怪的實作內容,也沒有什麼好隱藏的,所以最後決定將做好的樹狀選單的階層資料維護功能提供給大家,將整個 Solution 放到 GitHub 上面,所以這一篇文章只會簡單說明如何使用 jQuery EasyUI TreeGrid 做出這樣一個階層資料維護功能,其餘的就請各位自己去 GitHub 抓檔案下來看。

 


jQuery EasyUI TreeGrid

http://www.jeasyui.com/demo/main/index.php?plugin=TreeGrid

可以在 Gird 裡呈現樹狀資料,為 jQuery EasyUI 的 DataGrid 與 Tree 兩種功能的綜合體。

Documentation:http://www.jeasyui.com/documentation/treegrid.php

 

範例專案開發環境:

Visual Studio 2012, LocalDB,
.NET Framework 4.5
ASP.NET MVC 4
C#,
jQuery 1.8,2
jQuery EasyUI 1.3.2

 

功能畫面

管理主畫面

image

編輯

image

編輯完成

image

這邊特別說明 TreeGrid 的 Index,以下是 View 的原始碼內容,

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_TreeGridLayout.cshtml";
}
 
<h2>ASP.NET MVC + jQuery EasyUI - TreeGrid</h2>
 
@Html.ActionLink("Home", "Index", "Home")
<input type="button" value="重新整理" id="ButtonRefresh" />
<input type="button" value="新增節點" id="ButtonCreate" />
<hr />
 
<table id="TreeGrid"></table>
 
<!--編輯Dialog-->
@Html.Partial("_Edit")
 
@section scripts
{
    <script type="text/javascript" src="~/Scripts/project.js"></script>
    <script type="text/javascript" src="~/Scripts/project.TreeNode.js"></script>
    <script type="text/javascript">
        $(document).ready(function () {            
            var actionUrls =
            {
                HasRootNode: '@Url.Action("HasRootNode", "TreeGird")',
                LoadTreeNodeDDL: '@Url.Action("LoadTreeNodeDDL", "TreeGird")',
                GetTreeNodeJSON: '@Url.Action("GetTreeNodeJSON", "TreeGird")',
                Create: '@Url.Action("Create", "TreeGird")',
                GetTreeNode: '@Url.Action("GetTreeNode", "TreeGird")',
                Update: '@Url.Action("Update", "TreeGird")',
                Delete: '@Url.Action("Delete", "TreeGird")',
                MoveUp: '@Url.Action("MoveUp", "TreeGird")',
                MoveDown: '@Url.Action("MoveDown", "TreeGird")'
            };
 
            project.TreeNode.Initialize(actionUrls);
        });
 
    </script>
}

從 View 的原始碼可以看到東西很少,HTML Tag 沒有多少,呈現 TreeGrid 的部份也只有一個簡單的 table tag,另外把編輯節點資料的部份給抽出為 Partial View,而 Javascript 程式的部份也是抽出去為 project.TreeGrid.js。

這邊要特別說明有關 Javascript 的地方,在上面的原始碼裡,我是在 jQuery  document ready 的地方把 Javascript 會用到的 Controller Action 位置使用 object literal 傳到 project.TreeGrid.js,利用這樣的方式就可以不用因為需要取得 Controller Action 位置的關係而將 Javascript 程式給寫在 View 裡面,讓 View 與 Javascript 程式得以分離。

image

至於 project.js 與 project.TreeGrid.js 的 Javascript 程式寫法,我並不想多做解釋,不能夠理解我這樣寫法的朋友,如果只是硬把程式拿到自己的專案裡使用,應該會產生很多問題的,所以不建議直接把程式拿到自己的程式裡,而是想辦法了解一下裡面的寫法,其實並不是很難,用簡單的方式來說,我所使用的 Javascript 程式寫法是可以避免全域變數的影響,讓程式能夠容易重用,另外就是結構化。

再來就是後端程式的部份,主要是在 TreeNodeService 這個程式裡,這邊的 method 大多是給 TreeGridController 使用,

image

image

 

而將階層資料顯示為樹狀選單是在 HomeController,HomeController 三個顯示樹狀選單的處理,會是透過 EasyUITreeHelper.cs,

image

image

 

GitHub

這次把專案給上傳到 GitHub,以這個方式分享給大家,主要是 GitHub 取得檔案的方式算是相當快速與方便,另外如果各位有回報任何程式上的問題,我也可以將更新的檔案 Commit 上去,讓大家可以隨時更新。

所以往後如果有需要提供原始碼出來時,就會放在 GitHub 上,如果不需要 Clone 專案或是下載專案的朋友,也可以在 GitHub 上面直接看程式內容。

Repository 位置:https://github.com/kevintsengtw/MVC4_jQueryEasyUI_Tree_TreeGrid

image

 

如果有任何問題,或是程式有發現到錯誤的話,都歡迎各位隨時回報給我,謝謝。

 

以上

4 則留言:

  1. 你好, 我在網站開發美學的書上,沒看到TreeGrid的用法,
    另我有download你的範例來執行,
    發現範例中只有幾筆資料,但效能很慢, 在上下移資料時也要很一下,才會改變狀態, 而同事也提過這UI的效能不好,
    是否有效能比較好的 TreeGrid 且有新增/編輯功能的元件可推薦
    ? 謝謝

    回覆刪除
    回覆
    1. 你好,首先我並不是「ASP.net MVC 4 網站開發美學」的作者,
      所以他們的書也就不會有我的程式範例,
      至於效能快慢的問題,這只是範例程式,所有動作都是透過 AJAX 處理,所以每一個移動都是一個 Request,
      如果要快速的方式也有,將所有的移動都在前端程式裡(Javascript)做處理,最後再一次送回後端做更新也可以,
      jQuery EasyUI 效能的好與不好,應該是看怎麼使用,可見我用得不好,所以才會讓你這樣覺得。

      至於是否有效能比較好的 TreeGrid 且有新增/編輯功能的元件?
      我想應該是有的,不過我就不知道了,又要有 Tree 又要有 Grid 又要有新增與編輯功能......
      其實你可以分析一下需要怎麼做才能有這些功能,或是自己實作一個,就可以知道效能的瓶頸是在哪邊了。

      刪除
    2. 事隔一年的補充,如果執行這個範例程式有遇到提問者所說的「只有幾筆資料,但效能很慢, 在上下移資料時也要很一下,才會改變狀態」,如果是在 Visual Studio 裡按下 F5 以偵錯模式去執行網站,執行效能一定是很慢又很差,因為開啟 Visual Studio 的偵錯模式時會去追蹤程式執行的過程,也會載入相依的元件來做執行,所以整體的執行效能就不會很好,但如果你把範例程式發行到本機的 IIS 或是測試用 Server 的 IIS,就會發現到其實執行速度與效能與使用 Visual Studio 偵錯模式執行網站有很大的差別。
      這樣的差異與區別,這是開發人員應有的認知與常識。

      刪除
  2. 您好,這篇TreeGrid的教學非常完善,幾乎各種後台管理系統都會使用此功能進行頁面的管理,想學這個功能很久了,兩個多禮拜前開始跟著這系列三篇教學練習,原本很想偷懶直接copy扔進專案去用,後果就是因為不熟悉所以東少一塊西少一塊,最後還是乖乖的從第一章慢慢做,總算順利的完成。

    另外,在玩的時候發現一個小bug,在此提出簡易的修正方法
    發生方式:開啟TreeGrid後,先選擇"編輯節點",取消退出或存檔退出,再選擇"新增節點",此時儲存時會提示 無此節點 ID 資料
    這是因為在Create時沒有指定current.EditType為Create狀態,因此殘留著編輯後記錄的Update

    調整方式:在ButtonCreate事件給予current.EditType Create的值 即可,修改後的關鍵程式碼如下
    檔案名稱:project.TreeNode.js
    程式位置:
    $('#ButtonCreate').click(function () {
    current.MoveDownEditType = 'Create';
    current.Initilaize_TreeNodeDLL();
    current.EditType = 'Create';//點擊新增節點時,指定編輯Type為新增
    $('#EditDialog').dialog('open').dialog('setTitle', '新增節點');
    $('#EditForm').form('clear');
    $('#ParentNode')[0].selectedIndex = 0;
    });

    回覆刪除

提醒

千萬不要使用 Google Talk (Hangouts) 或 Facebook 及時通訊與我聯繫、提問,因為會掉訊息甚至我是過了好幾天之後才發現到你曾經傳給我訊息過,請多多使用「詢問與建議」(在左邊,就在左邊),另外比較深入的問題討論,或是有牽涉到你實作程式碼的內容,不適合在留言板裡留言討論,請務必使用「詢問與建議」功能(可以夾帶檔案),謝謝。