在做權限系統的時候,需要有一個樹形的菜單。下圖就是一個樹形菜單的樣式

但問題是,我們可以實現寫死的樹形菜單。什么是寫死的?就是在前台代碼中寫好要加載的樹形菜單是什么樣子的。但是我們權限系統的要求是動態加載樹形菜單,也就是根據數據庫里面表的內容動態加載。
我首先要說的就是數據庫設計,要想動態加載成樹形菜單,數據庫表中就一定要設置父節點ID和自身ID。通過父節點ID判斷自身是屬於哪一級菜單,而通過自身ID判斷其對應的下一級菜單。這是數據庫設計應該注意的地方,如果沒有父節點和自身子節點,那么就沒辦法實現動態加載樹形菜單。
動態加載樹形菜單的實現利用的zTree。這里順便提一下,zTree的網站做的真的很好,而且各種類型的zTree做的非常完美。我就是利用zTree來實現的,只不過與之不同的是zTree實現的樹菜單也是在前台寫好的,我們要做的就是將后台用數據庫查詢到的代碼拼接成前台已經寫好的代碼格式。
這是前台寫好的樹菜單格式:

我們要做的就是將前台這種樹形菜單格式在后台拼出來,而在樹形菜單中顯示的菜單名稱是從數據庫中查詢出來的。最開始的時候嘗試拼JSON串,但是事實證明,我失敗了,拼出來的字符串運行的時候根本顯示不出來

拼出的JSON串跟咱們要拼接的格式是不同的,JSON串拼接出來的格式適用於結構比較簡單,這樣利用循環可以將需要的字符串拼接出來。而我們需要的字符串是需要判斷下一級是否有子節點的,這個利用JSON串我沒有實現,只能實現一級菜單,而對應的實現三級菜單我沒有拼出來。很遺憾,但是利用循環、遍歷和DataTable的查詢,最終實現了樹形菜單字符串的拼接。下面是我實現的代碼
這個對應的實現二級菜單的拼接
- public string getTree(string strTree)
- {
- string Chilstr = "";
- //獲取DataTable
- zTreeBLL zTree = new zTreeBLL();
- DataTable dt = new DataTable();
- dt = zTree.QueryResource();
- //查詢父節點有多少條不重復的數據
- zTreeBLL zTree1 = new zTreeBLL();
- DataTable dt1 = new DataTable();
- dt1 = zTree1.QueryParidNum();
- //父節點只能加到4
- //for (int p = 0; p < Convert.ToInt32(dt1.Rows[0][0]); p++) //Convert.ToInt32強制轉換字符,把Object類型轉換成int
- //{
- int parentId = 0;
- //查找第一個父節點有多少個,即初值為0的父節點
- DataRow[] rowsP = dt.Select("ParentID=" + parentId);
- //利用循環將父節點拼接起來
- for (int i = 0; i < rowsP.Length; i++)
- {
- //把rowsP里面的數值取出來
- foreach (DataRow drP in rowsP)
- {
- string parName = drP["ResourceName"].ToString();
- //strTree = "[{name:\""+ parName + "\"";
- strTree = "[{name:\"" + parName + "\"";
- DataRow[] rowsC = dt.Select("ParentID=" + parentId + 1);
- if (rowsC.Length > 0) //如果子節點不為0,則開始拼接子節點的字符串
- {
- //利用循環將父節點對應下的子節點串起來
- foreach (DataRow drC in rowsC)
- {
- string chilName = drC["ResourceName"].ToString();
- Chilstr = Chilstr + "{name:\"" + chilName + "\"}";
- Chilstr = Chilstr + ",";
- }
- Chilstr = Chilstr.Remove(Chilstr.LastIndexOf(","), 1);
- strTree = strTree + ",children:[" + Chilstr + "]}];";
- }
- else
- {
- strTree = strTree + "\"}];";
- }
- }
- }
- // parentId++;
- //}
- return strTree;
- }
這個對應的是多級菜單的拼接
- public string getTree(string strTree)
- {
- string Chilstr = "";
- //獲取DataTable
- zTreeBLL zTree = new zTreeBLL();
- DataTable dt = new DataTable();
- dt = zTree.QueryResource();
- //查詢父節點有多少條不重復的數據
- zTreeBLL zTree1 = new zTreeBLL();
- DataTable dt1 = new DataTable();
- dt1 = zTree1.QueryParidNum();
- //父節點只能加到4
- //for (int p = 0; p < Convert.ToInt32(dt1.Rows[0][0]); p++) //Convert.ToInt32強制轉換字符,把Object類型轉換成int
- //{
- int parentId = 0;
- //查找第一個父節點有多少個,即初值為0的父節點
- DataRow[] rowsP = dt.Select("ParentID=" + parentId);
- //利用循環將父節點拼接起來
- for (int i = 0; i < rowsP.Length; i++)
- {
- //把rowsP里面的數值取出來
- foreach (DataRow drP in rowsP)
- {
- string parName = drP["ResourceName"].ToString();
- //strTree = "[{name:\""+ parName + "\"";
- strTree = "[{name:\"" + parName + "\"";
- DataRow[] rowsC = dt.Select("ParentID=" + parentId + 1);
- if (rowsC.Length > 0) //如果子節點不為0,則開始拼接子節點的字符串
- {
- //利用循環將父節點對應下的子節點串起來
- foreach (DataRow drC in rowsC)
- {
- string Threestr = "";
- //判斷二級菜單下對應的ID,也就是查找三級菜單的ParentID
- string chilFollow = drC["ID"].ToString();
- //查詢三級菜單
- DataRow[] rowsThree = dt.Select("ParentID=" + chilFollow);
- //判斷是否存在三級菜單
- if (rowsThree.Length > 0)
- {
- foreach (DataRow drThree in rowsThree)
- {
- string ThreeName = drThree["ResourceName"].ToString();
- Threestr = Threestr + "{name:\""+ThreeName+"\"}";
- Threestr = Threestr + ",";
- }
- Threestr = Threestr.Remove(Threestr.LastIndexOf(","), 1);
- string chilName = drC["ResourceName"].ToString();
- Chilstr = Chilstr + "{name:\"" + chilName + "\",children:["+Threestr+"]},";
- }
- //如果不存在三級菜單的話直接加載二級菜單
- else
- {
- string chilName = drC["ResourceName"].ToString();
- Chilstr = Chilstr + "{name:\"" + chilName + "\"}";
- Chilstr = Chilstr + ",";
- }
- }
- Chilstr = Chilstr.Remove(Chilstr.LastIndexOf(","), 1);
- strTree = strTree + ",children:[" + Chilstr + "]}];";
- }
- else
- {
- strTree = strTree + "\"}];";
- }
- }
- }
- return strTree;
- }
最終實現的效果

其實實現這個例子的方法還有很多種,比如說遞歸。雖然JSON串沒有拼接成功,但是我覺得JSON串是可以實現的。只是鑒於個人能力的緣故最終沒有拼接成功。動態加載樹形菜單終於實現的,但是還有很多需要改進的地方,比如如何將這個方法封裝起來,以至於可以無限的調用沒有缺陷等,這是下一步值得繼續探討的問題。
