虽然快捷菜单在桌面应用程序中已经是非常通用的元素但是由于在象ASPNET这样的基于服务器的技术没有很好的描绘所以在Web应用程序中快捷菜单并不是很通用要想使用快捷菜单浏览器必须高度支持DHTML和丰富事件模式例如Microsoft Internet Explorer 及更高版本或者Netscape 等然而各种浏览器的对象模式虽然功能上大至相同但是成员各名字却各不相同这就需要我们自己实现对象和事件的从一种模式到到另一种模式的转换
这里我们创建一个针到Internet Explorer的对象模式的ASPNET快捷菜单接着我将经过修改使其功能支持其它浏览器
ContextMenu Control 快捷菜单控件概述
MSDN Liabrary中包含了几个DHTML快捷菜单的示例分别提供了对这一功能的不能实现方法一个快捷菜单就是在页面中任何位置的一组标记代码它包括两部分内容——界面和脚本(当用户在页面右击时关联UI)UI提供一个可点击的元素的列表——菜单项——和各自的内容文本图标命令名(command name)目标url提示(tooltip)和所有你认为有必要显示出来的东西快捷菜单界面是页面的一部分并且属于页面控件树中的一员(太多的快捷菜单将会出现执行的问题与大多数用户的常规情况相比ASPNET将发送更多的快捷菜单到浏览器)当用户在页面的一个元素上右击时将引发一段JavaScript这段脚本将快捷菜单移动到右击的位置显示
快捷菜单将保持隐藏属性只有当用户在页面的一个绑定个快捷菜单的元素上右击时快捷菜单才显示页面元素接收脚本事件并弹出一个快捷菜单作为响应脚本事件信赖于浏览器在Internet Explorer 和更新版本中是 OnContexMenu事件在Netscape和更新版本中你要使用 OnMouseUp 事件(在Internet Explorer +中你也可能使用OnMouseUp事件但要多写几行代码)在接收事件的脚本中获取快捷菜单的UI代码块并且将它移动到发生点击的位置同时设置弹出的panel的 visibilty属性当用户在菜单项上点击时页面回传并引发服务器端事件对于服务器而言点击一个菜单项和点击一具常规的按钮没什么区别
当用户户想取消已经打开的快捷菜单时怎么办呢?在windows程序中按下Esc键或者在菜单区域外点击都可以取消已弹出的快捷菜单所以你必须在Web中实现这一功能请注意只有快捷菜单处于活动(显示出来)时Esc键才有郊因为Esc还可用于其它元素的其它键盘快捷方式
我还可以让菜单在用户鼠标移开菜单时隐藏可以通过脚本操作OnMouseLeave 事件实现
使用弹出菜单控件
假定我们已以设计出了这个弹出菜单(我们一会儿再说如何实现这个快捷菜单控件)那么如何使用它在ASPNET页面中添加一个或多个快捷菜单呢?首先在Visual Studio? NET的工个栏中拖一个或多个快捷菜单控件到页面上然后为每个菜单添加菜单项并配置每个菜单项的的工具提示命令名(command name)和其它所需的内容例如快捷键和帮助主题的链接命令名(command name)用于在响应点击快捷菜单发生页面回传时确定是哪一个菜单项被点击;对每一个快捷菜单控件实例的菜单项集合它必须是唯一的
你必须在HTML标签的OnContextMenu事件中加入代码来弹出快捷菜单代码必须信赖一系列的参数象点击的xy坐标点击的元素和要使用的快捷菜单的实例等注意如果必要你可以使用这种方式完全代替浏览器的快捷菜单绑定到OnContextMenu事件执行的JavaScript代码是在运行时动态生成的ContextMenu控件将暴露一个集合属性来包含分绑定快捷菜单的控件集合在ContextMenu控件将在运行时给这些要绑定的控件一个 oncontextmenu 属性OK!完成!可以测试了
慢着让我们先来想一下ContexMenu控件和页中任意的显示快捷菜单的元素的绑定机制这种机制对设计时的支持怎么样?理想的情况是根据基类每一个Web控件直接暴露一个 ContextMenuId属性然后在属性窗口中选择这个属性时将看到在页面中的ContextMenu控件的列表当然这些ContextMenu控件我们是已经创建了的;ContextMenuId属性在ASPNET x中不支持在将来的ASPNET中也不支持
在Visual Studio NET 集成开发环境中ASPNET复合控件可以很好的完成这一工作可以通过使用类撰写组合现有控件来创作新控件复合控件可呈现一个重新使用现有控件功能的用户界面复合控件可以从子控件的属性合成属性并处理由子控件引发的事件它还可以公开自定义属性和事件
我不选择使用复合控件有以下几个原因一个是Visual Studio NET 对于Web窗体中的控件功能的扩展支持的不好(请参见Extender provider components in ASPNET: an IExtenderProvider implementation)第二在Visual Studio 的ASPNET设计器中不再支持组件托盘区Web窗体设计器现在仅支持ASPNET控件而忽略象复合控件这样的非可视化的组件Visual Studio 将不再信赖InitializeComponent节并且不再在代码文件中自动添任何工具生成(toolgenerated)的代码ASPNET控件也不设计成具有快捷菜单所以要绑定快捷菜单只能通过快捷菜单控件自身的执行这里我使用类似ASPNET验证控件和被验证控件之间关联的形式