摘要:[ASP.NET] 搭配Menu控制項,自製簡易的 SiteMapPath
距離上次,已經好久沒發文了!Orz.... 怠惰真可怕!
最近在開發網站時,發現 Menu 項目被選取時,無法將點選的項目反白,問Google大神,發現有很多人也有相同問題。
因為當 MenuItem 有設定網址時,點選該項目後,就會被導入到指定的網頁,因為不再同一個頁面,
所以相關資訊也就無法取得,自然就無法將點選的項目反白。
參考了網路上許多人的做法,決定使用網頁名稱與 MenuItem 中NavigateUrl 路徑字串的比對方式來解決這個問題。
解決了上述的問題後,又有個想法,如果想把點選到的功能項目名稱顯示出來,那就好像得用 SiteMapPath 的方式來完成。
因此,也首次嘗試使用 XML 的方式來建立 Menu 控制項中的 MenuItem 內容。
因為 SiteMapPath 預設只認 Web.sitemap 這個檔案,而且也必須要放在網站的根目錄,而我又把 Menu 控制項用的 XML 文件放到
App_Code 這個目錄中,也希望把 SiteMap 檔案也放到這裡面,不過似乎不行。
不知道資質不夠還是觀念不好,怎麼弄都怎麼不好。
另外,而 SiteMap 檔的節點屬性似乎很少,也無法與自建的 XML 相容,一想到要維護兩份幾乎相同的文件就覺得很累也很懶,
所性就放棄了。
重新檢視了一下設定 Menu 控制項被點選項目反白的部分,發現可以結合MasterPage + MenuItem 的方式來建立自己簡易型的 SiteMapPath,
所以就將兩者結合起來。
建構簡要說明:
-
由於要讓每一頁都有相同的 SiteMapPath 顯示,因此利用 MasterPage 的便利性,將 Menu 控制項與
要顯示 SiteMapPath 字串的 Literal 控制項都放入到 MasterPage 中。
<form id="form1" runat="server"> <div> <asp:Menu ID="Menu1" runat="server"></asp:Menu> <hr /> 網站路徑:<asp:Literal ID="Literal1" runat="server"></asp:Literal> <hr /> <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server"> </asp:ContentPlaceHolder> </div> </form>
-
為了要簡單與順利設定被點選的目錄項目,因此製作了一個 MasterPage 的擴充功能 SetClickedMenuItem 與
一個用來尋找 MenuItem 項目的遞迴搜尋函數 RecurciveSearch 。
public static string SetClickedMenuItem(this MasterPage p, Menu m, bool SearchSubMenu ) { string pagename = VirtualPathUtility.GetFileName(p.Request.Url.PathAndQuery); return RecurciveSearch(m.Items, pagename, SearchSubMenu);; } private static string RecurciveSearch(MenuItemCollection mc, string MatchText, bool SearchSubMenu) { string tmp = ""; foreach (MenuItem mi in mc) { if (mi.NavigateUrl.IndexOf(MatchText) >= 0) { mi.Selected = true; return mi.Value; } if (mi.ChildItems.Count > 0 && SearchSubMenu) //找子目錄 { tmp = RecurciveSearch(mi.ChildItems, MatchText, SearchSubMenu); if (tmp.Length > 0) { return (mi.Text + " > " + tmp); } } } return ""; }
-
建立要用來產生 MenuItem 的 XML 檔案。
<?xml version="1.0" encoding="utf-8" ?> <MenuRoot url="~/index.aspx" title="首頁" description="首頁" value="首頁" > <MenuItem url="" title="主功能A" description="主功能A" value="主功能A"> <MenuItem url="~/fasub1" title="次功能項目1" description="次功能項目1" value="次功能項目1" /> <MenuItem url="~/fasub2" title="次功能項目2" description="次功能項目2" value="次功能項目2" /> </MenuItem> <MenuItem url="" title="主功能B" description="主功能B" value="主功能B"> <MenuItem url="~/fbsub1.aspx" title="次功能選單1" description="次功能選單1" value="次功能選單1" /> </MenuItem> <MenuItem url="" title="主功能C" description="主功能C" value="主功能C"> <MenuItem url="~/fcsub1.aspx" title="次功能項目1" description="次功能項目1" value="次功能項目1" /> <MenuItem url="~/fcsub2.aspx" title="次功能項目2" description="次功能項目2" value="次功能項目2" /> <MenuItem url="~/fcsub3.aspx" title="次功能項目3" description="次功能項目3" value="次功能項目3" /> </MenuItem> <MenuItem url="" title="主功能D" description="主功能D" value="主功能D"> <MenuItem url="~/fdsub1.aspx" title="次功能項目1" description="次功能項目1" value="次功能項目1" /> <MenuItem url="~/fdsub2.aspx" title="次功能項目2" description="次功能項目2" value="次功能項目2" /> </MenuItem> <MenuItem url="" title="主功能E" description="主功能E" value="主功能E"> <MenuItem url="~/fesub1.aspx" title="次功能項目1" description="次功能項目1" value="次功能項目1" /> <MenuItem url="~/fesub2.aspx" title="次功能項目2" description="次功能項目2" value="次功能項目2" /> <MenuItem url="~/fesub3.aspx" title="次功能項目3" description="次功能項目3" value="次功能項目3" /> </MenuItem> <MenuItem url="" title="登出" description="登出" value="EXIT"/> </MenuRoot>
-
最重要的就是要在 MasterPage 內 Menu 控制項的 DataBound 事件中做設定,這樣動作才會正常。
protected void menu_DataBound(object sender, EventArgs e) { if (!IsPostBack) { func_name.Text = this.SetClickedMenuItem(menu, true); } }
完成結果如下列展示圖:
最後:
雖然有點重複造輪子,但是也算是一個簡單的試做。
不過倒是有一些缺點,就是這網站路徑的內容產生完全是跟 Menu 控制項緊密的結合,
若不是在 Menu 的 Items 內的話,就無法出現相關資訊了。這部分應該是還有很多改進的空間!
文末,感謝各位觀賞,
也請各位前輩、先進多多指教。
以上!謝謝~
程式範例檔:MenuSiteMapPath.zip
參考資料:
- Menu Control Overview
- ASP.NET Site Navigation
- ASP.NET Site Maps
- How to: Configure Multiple Site Maps and Site-Map Providers
簡單就是美 :: { 簡單其實很不簡單 }