本文的目的是為啟用ASP.NET網站創建一個光滑且易於使用的菜單。為了實現這一目標,我們將使用ASP.NET菜單Web控件的標準功能,並通過使用級聯樣式表(CSS)純粹增強外觀。
對於那些熟悉CSS的人,本文的標題肯定會敲響鈴鐺。用於增強ASP.NET菜單控件外觀和感覺的CSS在列表中眾所周知的文章中刪除,標題為“ CSS的滑動門”。
在列表中的文章中,用來改善菜單外觀和感覺的CSS進行了詳盡的解釋。信用何時到期。感謝道格拉斯·鮑曼(Douglas Bowman)向我們提供CSS。如果您不熟悉,請務必先閱讀他的文章。
本文的重點是如何在ASP.NET環境中模擬此類菜單。讓我們開始...
讓我們啟動Visual Studio 2008,並使用ASP.NET Web應用程序項目模板創建一個新項目。此模板將自動添加默認的Web單是適當命名為“ Default.aspx”。在編輯器中打開它,然後從工具箱中添加菜單控件,您可以在“導航”選項卡下找到。如果您現在運行該網站,您將盯著空白頁。要使菜單顯示首先必須綁定到某些數據的所有內容。
定義菜單控件的數據的最簡單方法可以使用並使訪問者可以通過網站導航將其綁定到站點地圖。使用建議的“ web.sitemap”的名稱添加一個新的站點地圖項目。站點映射是一個XML文件,該文件以層次結構方式組織站點的頁面。另一個優勢是SiteMapDatasource控件會自動引用它。
接下來,在以下列表中顯示的站點地圖中添加一些頁面。
清單1- web.sitemap
<? xml version = " 1.0 " encoding = " utf-8 " ?>
< siteMap xmlns = " http://schemas.microsoft.com/AspNet/SiteMap-File-1.0 " >
< siteMapNode url = " " title = " " description = " " >
< siteMapNode url = " Default.aspx " title = " Home " description = " Take me back to the dasboard " />
< siteMapNode url = " Products.aspx " title = " Products " description = " Browse our catalog " />
< siteMapNode url = " Download.aspx " title = " Download " description = " Download neat stuff " />
< siteMapNode url = " Forum.aspx " title = " Forum " description = " Ask questions on our forum " />
< siteMapNode url = " Contact.aspx " title = " Contact " description = " Contact us " />
</ siteMapNode >
</ siteMap >現在,將SiteMapDataSource控件添加到頁面上,並將菜單控件的DataSourceID屬性設置為數據源的ID。還將菜單控件的方向屬性設置為水平,因為它默認為垂直。最後但並非最不重要的一點將STAWEMAPDATASOURCE的ShowStartingNode屬性設置為false。如果您不這樣做,則將顯示根節點,我們不想在菜單中包含此基本節點。您的代碼現在應該類似於清單2中顯示的代碼。
列表2 -Default.aspx
< asp:Menu
ID =" Menu1 "
runat =" server "
DataSourceID =" SitemapDataSource1 "
Orientation =" Horizontal "
> </ asp:Menu >
< asp:SiteMapDataSource
ID =" SiteMapDataSource1 "
runat =" server "
ShowStartingNode =" False "
/>如果您現在在瀏覽器中查看頁面,則應看到功能性但無聊的菜單。
圖1-平原水平菜單

在我們開始將CSS應用於菜單之前,還有另一個問題需要首先解決。如果您查看當您請求默認值時生成的生成的HTML代碼。 ASPX頁面時,您會注意到菜單控件不會生成最靈活的HTML代碼。默認情況下,它將每個菜單項包裝在表中。這並不適合輕鬆應用CSS。如果菜單控件生成一個包含所有菜單項的Unordererd列表,那就更好了。
幸運的是,可以使用控制適配器調整生成的HTML。控制適配器允許您渲染您喜歡的HTML。值得慶幸的是,這種控制適配器在CodePlex上很容易獲得。 CSS友好控制適配器套件提供了預製的控制適配器,其中包括ASP.NET菜單控件。
使用CSS友好控制適配器遵循以下步驟:
有必要使用源代碼並編譯CSSFriffly.DLL組件,因為我們需要調整適配器後來在本文中使用的一些CSS。
在將CSS友好項目添加到您的解決方案中時,Visual Studio轉換嚮導將彈出。只需執行轉換,一切都應該順利進行。轉換完成後,剩下的所有內容就是從ASP.NET網站項目中添加對CSSFriendly項目的參考。
只需運行網站並立即查看生成的HTML代碼即可。
清單3 -CSS友好的HTML代碼
< div class =" AspNet-Menu-Horizontal " id =" Menu1 " >
< ul class =" AspNet-Menu " >
< li class =" AspNet-Menu-Leaf AspNet-Menu-Selected " >
< a
href =" /Default.aspx "
class =" AspNet-Menu-Link AspNet-Menu-Selected "
title =" Take me back to the dasboard "
> Home </ a
>
</ li >
< li class =" AspNet-Menu-Leaf " >
< a
href =" /Products.aspx "
class =" AspNet-Menu-Link "
title =" Browse our catalog "
> Products </ a
>
</ li >
< li class =" AspNet-Menu-Leaf " >
< a
href =" /Download.aspx "
class =" AspNet-Menu-Link "
title =" Download neat stuff "
> Download </ a
>
</ li >
< li class =" AspNet-Menu-Leaf " >
< a
href =" /Forum.aspx "
class =" AspNet-Menu-Link "
title =" Ask questions on our forum "
> Forum </ a
>
</ li >
< li class =" AspNet-Menu-Leaf " >
< a href =" /Contact.aspx " class =" AspNet-Menu-Link " title =" Contact us "
> Contact </ a
>
</ li >
</ ul >
</ div >事情正在抬頭。
註釋:CSSFriendlyAdapters.Browser文件允許您指定應使用哪些CSS友好控制適配器。除了我要使用的適配器外,我還可以評論所有適配器。這樣,沒有其他控件是“適應”的,它們將繼續生成默認的HTML。
從您可以從適配器上方顯示的代碼中看到的菜單控件中顯示的代碼會自動為<ul> , <li>和<a>標籤注入必要的CSS類。這為我們節省了不得不定義這些問題的麻煩。
單頁包含多個適配器控件(例如菜單)也很常見。如果您想為每個控件具有獨特的外觀和感覺,請為適應的控件設置CSSSELECTORCLASS。例如,您可以設置CSSSELECTORCLASS屬性的值,如下所示:
清單4 -CSSSELECTORCLASS屬性
< asp:Menu
ID =" Menu1 "
runat =" server "
DataSourceID =" SitemapDataSource1 "
Orientation =" Horizontal "
CssSelectorClass =" PrettyMenu "
> </ asp:Menu >結果是由改編的控件生成的HTML代碼將包含在新層中( <div> )中。
清單5-包裝生成的HTML代碼
< div class =" PrettyMenu " id =" Menu1 " >
<!-- Other HTML code -->
</ div >請注意,此屬性是特定於CSS友好適配器的。這是一個自定義(Expando)屬性,您可以為此庫支持的控件設置它。您需要有關友好適配器工作方式的更多信息,請諮詢以下鏈接:
隨著CSSSELECTORCLASS周圍生成單獨的圖層( <div> ),並自動注入CSS類,我們終於準備好開始菜單。
使用的CSS與A列表的文章相似。如前所述,本文的重點不是CSS的結構,而是將其應用於ASP.NET菜單控件以獲取整潔的表格菜單。完成的結果可以在圖2中看到。
圖2-完成的結果

在下載頁面上,您可以找到本文的源代碼。它包含樣式表和必要的圖像。只需執行以下步驟即可重新創建完成的結果:
<Pages>節點的主題屬性。 (請參閱清單6)清單6- web.config摘錄
< system .web>
<!-- ... -->
< pages theme = " Default " >
<!-- ... -->
</ pages >
<!-- ... -->
</ system .web>我的解決方案中使用的CSS與列表中的文章相似,但是有一些更改。主要的變化與CSS友好適配器應用的CSS結構相關。
為了應用CSS,正確的結構需要使用。在通過友好適配器調整HTML的控件時,我發現使用白皮書中提到的圖表很方便。這些圖清楚地向您展示了CSS的結構。
您可以在此處找到菜單控件的圖。
我經常在許多論壇上提出的一個問題是如何實現水平子菜單,當用戶從頂級菜單中選擇其他選項卡時會發生變化。為了創建這個問題,我們首先需要調整我們的站點圖。
清單7顯示了調整後的站點圖。
清單7- web.sitemap帶有“子菜單項”
<? xml version = " 1.0 " encoding = " utf-8 " ?>
< siteMap xmlns = " http://schemas.microsoft.com/AspNet/SiteMap-File-1.0 " >
< siteMapNode url = " " title = " " description = " " >
< siteMapNode url = " Default.aspx " title = " Home " description = " Take me back to the dasboard " >
< siteMapNode url = " About.aspx " title = " About us " description = " " />
< siteMapNode url = " Foo.aspx " title = " Foo " description = " " />
< siteMapNode url = " Bar.aspx " title = " Bar " description = " " />
</ siteMapNode >
<!-- ... -->
</ siteMap >為了簡化的清單,僅顯示家庭節點的子菜單項(節點)。在源代碼中查看Web.sitemap的完整版本。現在,當您使用此網站圖瀏覽網站時,您會看到圖3中顯示的效果。
圖3-子菜單項

為了禁用此效果,如列表8所示,將菜單控件的最大dynamicDisplaylevels屬性設置為零。
清單8-最大dynamicdisplaylevels屬性
< asp:Menu
ID =" Menu1 "
runat =" server "
DataSourceID =" SitemapDataSource1 "
Orientation =" Horizontal "
CssSelectorClass =" PrettyMenu "
MaximumDynamicDisplayLevels =" 0 "
> </ asp:Menu >接下來,添加第二個菜單和SiteMapDataSource控件,並設置其屬性,如列表9所示。
清單9-子菜單控件
< asp:Menu
ID =" Menu1 "
runat =" server "
DataSourceID =" SitemapDataSource1 "
Orientation =" Horizontal "
CssSelectorClass =" PrettyMenu "
MaximumDynamicDisplayLevels =" 0 "
>
</ asp:Menu >
< asp:Menu
ID =" Menu2 "
runat =" server "
DataSourceID =" SitemapDataSource2 "
Orientation =" Horizontal "
CssSelectorClass =" PrettySubMenu "
>
</ asp:Menu >
< asp:SiteMapDataSource
ID =" SiteMapDataSource1 "
runat =" server "
ShowStartingNode =" False "
/>
< asp:SiteMapDataSource
ID =" SiteMapDataSource2 "
runat =" server "
StartingNodeOffset =" 1 "
ShowStartingNode =" False "
/>我們基本上告訴第二個菜單,它應該顯示站點映射中的第二級節點,並且不應顯示與第一個菜單所選選項卡相對應的啟動節點。
另外,第二個菜單的CSSselectorClass設置為PrettySubMenu。此菜單的CSS與第一個菜單相似。如果要檢查出來,請下載源代碼。現在運行該網站將為您帶來這個柔軟的結果。
圖4-樣式的子菜單項

最後一個問題需要解決。為了說明這個問題,需要重新組織項目。
首先,讓我們將主頁添加到名為site.master的項目中。將代碼,菜單和數據源(從默認為aspx頁面)移至主頁上,然後將其放在體內的第一個內容座位上。之後,您可以安全地刪除default.aspx頁面。
現在,讓我們在項目中添加一些Web內容表單項目。添加與網站圖及其子節點的第一個節點的項目相對應的Web內容表單,即:
請確保選擇site.master作為這些Web內容表單中的每一個的主頁。網絡中提到的其他頁面純粹是出於說明目的。
再次啟動網站,然後導航到FOO頁面。這將揭示問題。
圖5-選擇問題

因為我們已經導航到網站映射的底層,所以頂級菜單不知道它應該標記為選定的菜單項。為了解決此問題,我們將需要在主頁的主頁上進行一些編碼。
清單10顯示了您必要的代碼。
清單10-選擇正確的頂級菜單項
namespace MenuWebApplication
{
public partial class Site : System . Web . UI . MasterPage
{
private static string ExtractBaseUrl ( string url )
{
return url . Contains ( "?" ) ? url . Remove ( url . IndexOf ( '?' ) ) : url ;
}
protected void Page_Load ( object sender , EventArgs e )
{
Menu1 . DataBind ( ) ;
// Which node in the site map is currently selected?
SiteMapNode currentNode = SiteMap . CurrentNode ;
if ( currentNode != null )
{
// Obtain the Url of the currently selected node's parent node.
string parentUrl = String . Empty ;
SiteMapNode parentNode = currentNode . ParentNode ;
if ( parentNode != null )
{
parentUrl = ExtractBaseUrl ( parentNode . Url ) ;
}
// Obtain the Url of the currently selected node.
string currentUrl = ExtractBaseUrl ( currentNode . Url ) ;
// Iterate the top level menu tier.
foreach ( MenuItem menuItem in Menu1 . Items )
{
// Compare the menu item's Url against the currently
// selected node's Url or the Url of its parent.
string menuItemUrl = ExtractBaseUrl ( menuItem . NavigateUrl ) ;
if ( ( currentUrl == menuItemUrl ) || ( parentUrl == menuItemUrl ) )
{
// If either matches then mark the top level menu item as selected.
Menu1 . Items [ Menu1 . Items . IndexOf ( menuItem ) ] . Selected = true ;
break ;
}
}
}
}
}
}現在,您可以自由選擇任何子菜單項。它是相應的頂級菜單項,將繼續選擇,以使訪客有一個視覺線索,了解他目前位於網站中的位置。
圖6-固定的選擇問題

建立一個帶有上下文敏感的水平子菜單的精美表格菜單是很多工作,但最終您會以光滑的外觀和用戶友好的菜單結束。
我建議您在用戶控件中實現此類菜單,並在網站的主頁上包含該用戶控件。在大多數情況下,將在整個網站中使用一種這樣的菜單。