16.4 Menu服务器控件
ASP.NET 2.0中还引入了一个更酷的导航控件,即新的Menu服务器控件。这个控件很适合让终端用户在较大的选项层次结构中导航,在这个过程中很少利用浏览器的资源。图16-19显示了完全折叠或完全展开层次结构的一个分支时Menu控件的外观。

图 16-19
从图中可以看出,所显示的第一个Menu控件是Home链接,在该链接的右边有一个小箭头。这个箭头表示在层次结构中,这个顶级链接还包含更多的选项。第二个Menu控件显示了终端用户进入站点地图提供的一个分支时控件的默认外观。
当有许多选项时—— 无论这些选项是终端用户可以选择的选项,还是应用程序提供的导航点,使用Menu控件是非常理想的。Menu控件可以提供许多选项,且在该过程中几乎不占用空间。
在ASP.NET应用程序中使用Menu控件是很简单的。Menu控件要使用SiteMap DataSource控件。可以将SiteMapDataSource控件和Menu控件拖放到Visual Studio 2005设计界面上,使用Menu控件的DataSourceId属性把它们连接起来。还可以直接在代码中创建和连接它们。程序清单16-16是最简单的Menu控件的示例。
程序清单16-16 Menu控件的简单用法
<%@ Page Language="VB" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Menu Server Control</title>
</head>
<body>
<form id="form1" runat="server">
<asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" />
<asp:Menu ID="Menu1" runat="server" DataSourceID="SiteMapDataSource1">
</asp:Menu>
</form>
</body>
</html>
在这个例子中,使用SiteMapDataSource控件自动处理应用程序的Web.sitemap文件。该示例包含的另一项是Menu控件,它使用经典的ID和Runat属性,并使用DataSourceID属性把它连接到从SiteMapDataSource控件提取出来的数据上。
默认的Menu控件非常简单,通过重新定义该控件的属性,可以高度定制它的外观和操作方式。下面几节就介绍几个修改Menu控件外观和操作方式的例子。
16.4.1 给Menu控件应用不同的样式
Menu控件默认显示为平面外观。如果要保留这个外观,可以使用该控件的默认属性设置,也可以改变字号和样式,使之符合站点的要求。实际上,修改这个控件有许多方式,使它的外观比较新颖独特,并与站点的其他内容相匹配。可以定制这个控件的外观,也可以使用该控件的预定义样式。
1. 使用预定义的样式
Visual Studio 2005包含一些可以用于Menu控件的预定义样式,把它的外观和操作方式快速应用于菜单项。所提供的样式有Classic和Professional等。要应用这些预定义样式,可以在页面的设计视图上使用Menu控件。在设计视图中,突出显示Menu控件,展开该控件的智能标记,此时可以看到处理该控件的一列选项。要改变该控件的外观和操作方式,可单击Auto Format链接,选择一个样式。
执行这个操作会应用一系列样式属性,改变该控件的代码。例如,如果选择Classic选项,结果如程序清单16-17所示。
程序清单16-17 把样式应用于Menu控件上时代码的变化
<asp:Menu ID="Menu1" runat="server" DataSourceID="SiteMapDataSource1"
BackColor="#B5C7DE" ForeColor="#284E98"
Font-Names="Verdana" Font-Size="0.8em" StaticSubMenuIndent="10px"
DynamicHorizontalOffset="2">
<StaticSelectedStyle BackColor="#507CD1"></StaticSelectedStyle>
<StaticMenuItemStyle HorizontalPadding="5"
VerticalPadding="2"></StaticMenuItemStyle>
<DynamicMenuStyle BackColor="#B5C7DE"></DynamicMenuStyle>
<DynamicSelectedStyle BackColor="#507CD1"></DynamicSelectedStyle>
<DynamicMenuItemStyle HorizontalPadding="5"
VerticalPadding="2"></DynamicMenuItemStyle>
<DynamicHoverStyle ForeColor="White" Font-Bold="True"
BackColor="#284E98"></DynamicHoverStyle>
<StaticHoverStyle ForeColor="White" Font-Bold="True"
BackColor="#284E98"></StaticHoverStyle>
</asp:Menu>
在Menu控件中,有许多新增的样式可以改变显示在该控件中的菜单项。图16-20说明了这个样式选项显示在浏览器中的情况。

图 16-20
2. 改变静态项的样式
Menu控件把层次结构中的项看作静态或动态的。这个例子中的静态项是生成页面时显示的Home链接。动态链接是用户把鼠标停留在菜单中的Home链接上时动态出现的项。可以改变菜单中这两类节点的样式。
要把某个样式应用于静态链接,必须给Menu控件添加一个静态样式元素。Menu控件包含如下静态样式元素:
● <StaticHoverStyle>
● <StaticMenuItemStyle>
● <StaticMenuStyle>
● <StaticSelectedStyle>
● <StaticTemplate>
在这个列表中,重要的选项有<StaticHoverStyle>和<StaticMenuItemStyle>元素。<StaticHoverStyle>元素用于定义终端用户把鼠标停留在菜单中的静态项上时该静态项的样式。<StaticMenuItemStyle>元素用于定义终端用户不把鼠标停留在菜单中的静态项上时该静态项的样式。
程序清单16-1添加了一个样式,在终端用户把鼠标停留在静态项上时,应用该样式。
程序清单16-18 在Menu控件中给静态项添加一个hover样式
<asp:Menu ID="Menu1" runat="server" DataSourceID="SiteMapDataSource1">
<StaticHoverStyle BackColor="DarkGray" BorderColor="Black" BorderStyle="Solid"
BorderWidth="1"></StaticHoverStyle>
</asp:Menu>
当终端用户把鼠标停留在菜单中的静态项上时,这个小例子给该项添加了背景色和边框,结果如图16-21所示。

图 16-21
3. 给动态项添加样式
给Menu控件的动态项添加样式与给静态项添加样式一样简单。Menu控件包含许多不同的元素,可用于修改动态项的外观,如下所示:
● <DynamicHoverStyle>
● <DynamicMenuItemStyle>
● <DynamicMenuStyle>
● <DynamicSelectedStyle>
● <DynamicTemplate>
这些元素修改菜单项的方式与它们的静态版本相同,但只改变从静态项中动态弹出的项。程序清单16-19是把hover样式应用于动态项的例子。
程序清单16-19 把hover样式应用于Menu控件中的动态项
<asp:Menu ID="Menu1" runat="server" DataSourceID="Sitemapdatasource1">
<StaticHoverStyle BackColor="DarkGray" BorderColor="Black"
BorderStyle="Solid" BorderWidth="1"></StaticHoverStyle>
<DynamicHoverStyle BackColor="DarkGray" BorderColor="Black"
BorderStyle="Solid" BorderWidth="1"></DynamicHoverStyle>
</asp:Menu>
这段代码生成的结果如图16-22所示。

图 16-22
4. 修改菜单项的布局
在默认情况下,动态的菜单项从左到右显示。也就是说,菜单中的项在展开时,会以垂直方式显示。实际上,可以控制这种行为,还可以使用另一种方式。
另一种方式是把第一级菜单项显示在第一个静态项的下面(水平)。使用Menu控件的Orientation属性可以改变这种行为,如程序清单16-20所示。
程序清单16-20 使菜单项水平显示
<asp:Menu ID="Menu1" runat="server" DataSourceID="SiteMapDataSource1"
Orientation="Horizontal">
</asp:Menu>
这段代码生成的结果如图16-23所示。

图 16-23
Orientation属性的值只能是Horizontal或Vertical,其默认值是Vertical。
5. 改变弹出符号
生成的菜单项,无论是静态项还是动态项,都默认用箭头表示弹出符号。如图16-24所示。
![]()
图 16-24
不一定要使用这个箭头符号,实际上,可以把它改为一个图像。程序清单16-21说明了如何完成这个任务。
程序清单16-21 使用定制的图像
<asp:Menu ID="Menu1" runat="server" DataSourceID="SiteMapDataSource1"
Orientation="Horizontal" DynamicPopOutImageUrl="myArrow.gif"
StaticPopOutImageUrl="myArrow.gif">
</asp:Menu>
要把弹出符号改为我们选择的图像,应使用DynamicPopOutImageUrl或StaticPopOut ImageUrl属性。这些属性的String值是要使用的图像路径。根据所使用的图像,该属性会生成如图16-25所示的结果。

图 16-25
6. 用图像分隔菜单项
Menu控件的另一个样式选项可以给菜单项添加一个分隔图像。根据分隔图像所放置的位置,可以使用StaticBottomSeparatorImageUrl、StaticTopSeparatorImageUrl、Dynamic BottomSeparatorImageUrl和DynamicTopSeparatorImageUrl属性。
例如,如果要把分隔图像放在动态菜单项的下面,应使用DynamicBottom SeparatorImageUrl属性,如程序清单16-22所示。
程序清单16-22 给动态项应用分隔图像
<asp:Menu ID="Menu1" runat="server" DataSourceID="SiteMapDataSource1"
DynamicBottomSeparatorImageUrl="myDivider.gif">
</asp:Menu>
Menu控件中所有定义分隔图像的属性都带有一个String值,它指向该图像的位置。程序清单16-22的结果如图16-26所示。

图 16-26
16.4.2 Menu事件
Menu控件包含如下事件:
● DataBinding
● DataBound
● Disposed
● Init
● Load
● MenuItemClick
● MenuItemDataBound
● PreRender
● Unload
要注意的一个事件是MenuItemClick,这个事件如程序清单16-23所示,它可以在终端用户单击一个菜单项时执行一些操作。
程序清单16-23 使用MenuItemClick事件
VB
Protected Sub Menu1_MenuItemClick(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.MenuEventArgs)
' Code for event here
End Sub
C#
protected void Menu1_MenuItemClick(object sender, MenuEventArgs e)
{
// Code for event here
}
这个事件使用了MenuEventArgs事件委托,允许访问所选菜单项的文本和值。
16.4.3 把Menu控件绑定到XML文件上
与TreeView控件一样,也可以把Menu控件绑定到ASP.NET 2.0的其他数据源控件提供的项上。大多数开发人员都喜欢使用Menu控件,让终端用户导航到URL目的地,还可以使用Menu控件让用户作出选择。
例如,使用前面的XML文件Hardware.xml,在本章前面的程序清单16-8中该文件与TreeView控件一起使用。而在这个例子中,Menu控件与XmlDataSource控件一起使用。终端用户从菜单中选择一项时,就用选中的项填充页面上的Listbox。其代码如程序清单16-24所示。
程序清单16-24 使用Menu控件和XML文件
VB
<%@ Page Language="VB" %>
<script runat="server">
Protected Sub Menu1_MenuItemClick(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.MenuEventArgs)
Listbox1.Items.Add(e.Item.Parent.Value & " : " & e.Item.Value)
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Menu Server Control</title>
</head>
<body>
<form id="form1" runat="server">
<asp:Menu ID="Menu1" runat="server" DataSourceID="XmlDataSource1"
OnMenuItemClick="Menu1_MenuItemClick">
<DataBindings>
<asp:MenuItemBinding DataMember="Item"
TextField="Category"></asp:MenuItemBinding>
<asp:MenuItemBinding DataMember="Option"
TextField="Choice"></asp:MenuItemBinding>
</DataBindings>
</asp:Menu>
<p>
<asp:ListBox ID="Listbox1" runat="server">
</asp:ListBox></p>
<asp:xmldatasource ID="XmlDataSource1" runat="server"
datafile="Hardware.xml" />
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<script runat="server">
protected void Menu1_MenuItemClick(object sender, MenuEventArgs e)
{
Listbox1.Items.Add(e.Item.Parent.Value + " : " + e.Item.Value);
}
</script>
在这个例子中,没有像前面的TreeView控件一样使用<asp:TreeNodeBinding>元素,Menu控件使用的是<asp:MenuItemBinding>元素,来连接XML文件Hardware.xml中列出的项。另外,Menu控件的根元素<asp:Menu>现在包含OnMenuItemClick属性,它指向事件委托Menu1_ MenuItemClick。
Menu1_MenuItemClick事件包含事件委托MenuEventArgs,它能获得选中的子元素和父元素的值。在这个例子中,使用这两个元素的值填充Listbox控件,如图16-27所示。

图 16-27







