AMenu - 一个简单的 .NET 垂直菜单
一个基于 CSS 的 .NET 垂直菜单控件。
引言
AMenu 是一个简单的 .Net 包装器,用于一个基于 CSS 的“弹出式”垂直菜单。网上有很多关于 CSS 菜单工作原理的优秀文章,例如:http://www.seoconsultants.com/css/menus/tutorial。基本上,菜单是使用嵌套的 UL 元素实现的,其中每个 LI 都包含一个超链接。
CSS 的主要功能是隐藏/显示子菜单,并实现所需的布局。隐藏是通过在 UL 元素上使用 {disaply:none} 或将元素移出屏幕 {left:-5000px} 来完成的。子菜单是通过在 hover 伪类 中使用 子选择器 指定其位置来显示的:li:hover > ul {left:100%}.
以下是一个演示该概念的工作示例。请注意,为了清晰起见,已省略 IE6 特定的代码;此示例在除 IE6 之外的所有浏览器上都可以正常工作。
文件 test.htm
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>AMenu test</title>
<link href="amenu.css" type="text/css" rel="stylesheet" />
</head>
<body>
<div id="Menu3" class="amenu">
<ul class="top">
<li class="vpadding_top" />
<li><a href="#">Parts Catalog ...</a>
<ul class="sub">
<li class="vpadding_top">
<li><a href="#">Batteries</a></li>
<li><a href="#">Alternators</a></li>
<li class="vpadding_bottom" />
</ul>
</li>
<li class="vpadding_bottom" />
</ul>
</div>
</body>
</html>
实现
菜单实现为三个 WebControl 派生组件:AMenu、AMenuSub、MenuLink 和关联的样式表 amenu.css。
AMenu 类负责渲染 DIV 容器和顶级 UL。MenuLink 类渲染所有 LI 元素,包括子 A 元素。AMenuSub 渲染子菜单的 UL 元素。
下面的图片显示了最终的 DOM 树。屏幕截图是从包含的演示应用程序在 Firefox 上运行时截取的。

Internet Explorer 6
由于 IE6 不支持 CSS2,用于显示子菜单的 CSS 子选择器将不起作用。解决方法是将每个子菜单包装在 TABLE 中,并使其成为 A 元素(而不是 LI 元素)的子元素。这是通过为每个 A 元素生成条件注释来实现的。我不确定该巧妙解决方案应归功于谁,我最初是在 Stu Nicholls (http://www.cssplay.co.uk) 的工作中看到的。
下面的图片显示了在 IE6 上渲染的 DOM 树

Using the Code
菜单组件公开以下公共属性
AMenu
- ArrowImage
- 箭头图像的 URL。应为 10x10。默认值:无
- BackColor
- 菜单背景色。默认值:#F7F7F7
- BackHover
- 悬停背景色。默认值:#DAE0E4
- BorderColor
- 边框颜色。默认值:#C6C6CC
- Font-Bold
- 使用粗体字体?默认值:false。
- Font-Names
- 菜单字体名称。默认值:Arial。
- Font-Size
- 菜单字体大小。默认值:12px。
- ForeColor
- 菜单前景色。默认值:#336666。
- ForeHover
- 悬停前景色。默认值:蓝色。
- Border
- 为顶部菜单绘制边框?默认值:false。
- 高度
- 菜单高度。默认值:10em。
- 宽度
- 菜单宽度。默认值:190px。
- SubWidth
- 默认子菜单宽度。默认值:190px。
AMenuSub
- 宽度
- 子菜单宽度。默认值:无。
MenuLink
- 文本
- 菜单项的文本。
- IconImage
- 图标图像的 URL。默认值:无。
- CommandName
- 项的 CommandName 参数。默认值:无。
- CommandArgument
- 项的 CommandArgument 参数。默认值:无。
- PostBackUrl
- 提交到的页面的 URL。默认值:无。
- Enabled
- 项是否启用?默认值:是。
- OnClientClick
- 客户端处理程序。默认值:无。
- 工具提示
- Tooltip 文本。默认值:无。
事件
该控件提供了两种处理选择事件的选项。第一级,MenuLink 组件接受一个“OnClick”处理程序。如果指定,将调用此处理程序来处理选择,并且事件不会进一步冒泡。
在第二(顶部)级,AMenu 组件接受一个“OnItemClick”处理程序。如果指定,将调用此处理程序来处理来自所有没有处理程序的 MenuLink 的选择。
两个处理程序的签名与 LinkButton 相同void OnItemClick(object sender, CommandEventArgs e);
注意:仅当指定了 MenuLink 的 CommandName 参数时,才会调用处理程序。通常,CommandName、CommandArgument 和 PostBackUrl 的用法与 LinkButton 相同。
下面的图片显示了处理程序解析的事件参数

示例
以下是导言中的示例,但这次使用 AMenu。请确保您已包含对 amenu.dll 程序集的引用,并且 amenu.css 样式表可访问。
文件 test.aspx
<%@ Page Language="C#" CodeBehind="test.aspx.cs" Inherits="TestPage" %>
<%@ Register TagPrefix="mt" Namespace="mtweb" Assembly="AMenu" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>AMenu test</title>
<link href="amenu.css" type="text/css" rel="stylesheet" />
</head>
<body>
<form id="Form1" runat="server">
<mt:AMenu ID="Menu3" runat="server" Border="true" OnItemClick="OnItemClick">
<mt:MenuLink ID="PartsCatalog" runat="server" Text="Parts Catalog ...">
<mt:AMenuSub ID="SubParts" runat="server">
<mt:MenuLink ID="Batteries" runat="server" Text="Batteries" />
<mt:MenuLink ID="Alternators" runat="server" Text="Alternators" />
</mt:AMenuSub>
</mt:MenuLink>
</mt:AMenu>
</form>
</body>
</html>
文件 test.aspx.cs
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class TestPage : System.Web.UI.Page
{
protected void OnItemClick(object sender, CommandEventArgs e)
{
string from = ((Control)sender).ClientID;
string cmd = e.CommandName;
string arg = e.CommandArgument as string;
// ...
}
}
结果

限制
存在几项限制,您在使用此控件时可能会或可能不会遇到问题。无论如何,通过修改 amenu.css 样式表和菜单源代码,应该能够将控件适应特定场景。未公开几个属性。例如:您无法更改默认的 1px 边框而不修改 amenu.css 样式表以及 MenuLink.cs 中计算子菜单位置的方法。对于 MenuLink 文本的左边距(图标和文本之间的距离),或菜单项周围的 2px 填充,或 2em 的行高,也是如此。
不支持 Visual Studio 设计器。从工具栏拖动组件将不起作用。
生成的标记不是“流动的”。当用户配置其浏览器以强制使用特定的字体大小时(例如,Firefox 中的“最小字体大小”),子菜单将无法正确对齐。
结论
在大多数情况下,只需更改颜色方案和图标即可部署该控件。对于特定需求,源代码可以作为实现您自己的良好起点。包含的演示应用程序可能对那些刚开始接触 .NET 的人感兴趣。它使用动态加载的用户控件 (ascx)、更新面板(包括触发器和进度控件)、历史记录管理等等。
历史
2009/10/05 - 首次发布。
2009/10/07 - 修复了处理 PostBackUrl 的错误。
2009/10/08 - 对演示应用程序进行了小更新。