若堅持反覆研究之前的步驟,到了這裏,相信你不再對C#MVC懵懵懂懂了。進行到這裏也漸漸接觸到核心了。不得不停下業務,單開一篇講述一下我們這個Demo是如何加載菜單,顯示到easyui的tree上面的。實現方式有很多種,但是原理基本一致,
獲取數據源,綁定數據源,顯示(看着很廢話,好像什麼也沒告訴你,其實已經將最本質的告訴了你…)實際上很多控件和技術就是基於這個實現的。大部分東西,只要你到他的數據源在哪,綁定方式是什麼,基本沒什麼東西是難理解的,無非是應用了新的框架或是技術,這個東西網上檢索很容易得到解決方案。所以當你遇到一個問題的時候問問自己,數據源在哪。很多問題迎刃而解。(小小程序員的亂語,大牛請自動過濾)。
閒言不語,我們是通過xml文件獲取菜單信息,然後讀取xml信息,將其拼接成html,然後在easyui的tree控件上,可以直接顯示。以我淺薄的知識來看,是比較簡單的一種實現方式,並且減輕了服務器上數據庫的一些壓力,因爲大部分用戶的菜單很少變更,所以這種實現方式,雖然實現起來頗爲麻煩,但是還是有一定優勢的。當然最終的數據源是數據庫的表了,這裏的xml你可以理解爲一種緩存機制。
因爲我剛剛建的數據庫,裏面並沒有信息,所以我這裏自己建立一個xml文件,手動模擬幾個菜單,等全部項目寫完之後,我會回頭將這一塊獲取菜單的代碼重寫,那時候你應該會有一種,哦,原來如此 的感覺。
XML文件:
代碼:
<UserMenu>
<HderMenu MenuName="Setting" MenuUrl="" MenuIcon="icon-system">
<SubMenu MenuName="Menu Management" MenuUrl="/Admin/MenuList" MenuIcon="icon-system" />
<SubMenu MenuName="Access Management" MenuUrl="/Admin/AssignPermission" MenuIcon="icon-system" />
<SubMenu MenuName="Test" MenuUrl="/Test/Test" MenuIcon="icon-system" />
</HderMenu>
</UserMenu>
我來稍作分析:
:主節點,標識文檔的作用。
:父節點(其實不應該這麼叫,但是相對於菜單結構,它是父節點,爲了避免你們混亂),放置一級菜單節點,一級菜單,沒有太多意義,只是對下面的菜單的一個分類。
:子節點,放置二級菜單節點,這個纔是真正具有跳轉鏈接的菜單項。用戶根據其具有的url屬性,點擊後跳轉到相應的action,返回至相應的視圖。
屬性:MenuName,菜單名;MenuUrl,鏈接;MenuIcon,圖標信息;
我們瞭解了程序是根據xml加載數據的,那麼如何綁定呢?
這裏在common中,抽取了一個解析xml的方法,將xml的信息最終拼接成一段html片段,返回給視圖,然後視圖進行展示。
public static string LoadMenuXML(string xmlpath)
{
string usermenu = "";
XmlDocument doc = new XmlDocument();
if (!System.IO.File.Exists(xmlpath))
{
return "";
}
doc.Load(xmlpath);
XmlElement root = doc.DocumentElement;
for (int i = 0; i < root.ChildNodes.Count; i++)
{
XmlNode Hnodel = root.ChildNodes.Item(i);
usermenu += string.Format("<li data-options=\"iconCls:'icon-system',state:'closed'\"><span>{0}</span><ul>", Hnodel.Attributes["MenuName"].Value);
for (int j = 0; j < Hnodel.ChildNodes.Count; j++)
{
XmlNode Cnodel = Hnodel.ChildNodes.Item(j);
usermenu += string.Format("<li data-options=\"iconCls:'{0}'\"><a style=\"text-decoration:none;color:black;\" href=\"javascript:addTab('{1}','{2}')\">{3}</a></li>", Cnodel.Attributes["MenuIcon"].Value, Cnodel.Attributes["MenuName"].Value, Cnodel.Attributes["MenuUrl"].Value, Cnodel.Attributes["MenuName"].Value);
}
usermenu += string.Format("</ul></li>");
}
return usermenu;
}
對於沒有接觸過xml的朋友,這裏可以稱爲一個技術難點吧,我如果說讓你們自己網上檢索,會不會被噴?,這裏我稍作解釋:
XmlDocument doc = new XmlDocument();
建立一個xml對象,引入System.XML的dll即可使用。
doc.Load(xmlpath);
根據路徑加載xml到對象中,這個路徑是一個完整的路徑哦,包含文件物理路徑和文件名,文件後綴。這裏大牛應該看出來了,對這個文件是放在服務器上。這樣會對服務器造成一定的壓力(當用戶過多時),但是相比較那些對數據庫使用頻繁的系統,可以犧牲內存換取運行速度。
XmlElement root = doc.DocumentElement;
獲取根節點,也就是我們上面的節點。然後便利根節點下面的父節點(對於xml文件應該稱爲子節點)
XmlNode Hnodel = root.ChildNodes.Item(i);
usermenu += string.Format(“
- ”, Hnodel.Attributes[“MenuName”].Value);
獲取當前遍歷中的菜單父節點,並且遍歷該菜單父節點,查詢其所屬的菜單子節點。
並將父節點中的菜單信息,拼接進ul元素中。
這裏用了C#中字符串的Format方法,看一下官方api如何解釋:
將指定字符串中的一個或多個格式對象替換爲指定對象的字符串表示形式。
Hnodel.Attributes[“MenuName”].Value,將節點中屬性爲MenuName的值取出來賦給{0},
XmlNode Cnodel = Hnodel.ChildNodes.Item(j);
usermenu += string.Format(“
獲取當前遍歷的菜單子節點。並將子節點中的菜單信息拼接進li元素中。
最後我們就得到了一個包含所有菜單信息的html的片段,將這個片段直接返回給視圖,easyui就可以正常加載了。
看一下controller中的寫法:
public ActionResult Home()
{
User_Master userMaster = (User_Master)Session["UserMaster"];
ViewBag.User = userMaster.User_Name;
ViewBag.Date = DateTime.Now;
string userMasterId = userMaster.User_Master_Id.ToString();
string userMenuPath = System.Configuration.ConfigurationManager.AppSettings["UserMenuPath"].ToString().Trim();
string xmlPath = userMenuPath + userMasterId + ".xml";
ViewBag.MenuTreeList = MenuXMLHelper.LoadMenuXML(xmlPath);
return View();
}
那麼這個userMenuPath 在哪裏設置的呢?是在web下面的config文件中設置:
這樣,我們還需在自己本地建立相應爲問價夾,將剛剛的xml文件放進去,注意xml的命名哦,是以User_Maser_Id做的名字,這樣可以唯一標示該用戶的登錄菜單。
還要講我們之前在頁面註釋的tree放開哦:
最終顯示: