通过Visual studio 2005 中的web.sitemap实现OUTLOOK风格的系统菜单
Visual Studio 开发工具提供的一些功能让开发变得更加简单,比如 web.sitemap可以直接实现菜单导航,支持菜单模式和树的模式。 基本上菜单的变化,只需要配置一下 web.sitemap文件即可。但这个功能并不一定能让最终端的用户满意,因为界面的操作风格比较单一,也只是方便的集成一些微软模式的权限控制。
如何实现一个OUTLOOK风格的菜单,并集成自有的权限体系呢。
一级菜单展开、显示下级菜单、菜单权限控制、鼠标移动时高亮显示。。。。。
这样一个菜单如何通过web.sitemap实现的呢?
通过web.sitemap定义菜单结构及其它属性就可以实现这样的一个菜单风格
当然要达到这样的效果还是需要对web.sitemap的使用进行一些二次开发才能实现的。
1、扩展web.sitemap的一些属性
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" ><!--disenable为true表示显示全部菜单,如果没权限显示不可用,如果为false表示没有权限则移除--><siteMapNode title="主页" url="Newmain.aspx" target="_parent" disenable="true" startIndex="1"AdminIndex="9"> <siteMapNode title="我的桌面" img="skins/2004/images/icon/desktop.gif"menuIndex="1"url ="~\1.aspx"> <siteMapNode title="待办事项" url="~\Forms\frmContent.aspx" description="待办事项"targeturl="" /> <siteMapNode title="我登记事件" url="~\Forms\frmWaittingContent.aspx?TypeContent=MyReg" description="我登记事件"/> <siteMapNode title="出差授权" url="~\Forms\FrmAgentSet.aspx" description="出差授权"/> </siteMapNode> . <siteMapNode title="系统管理" img="skins/2004/images/icon/sKms.gif"menuIndex="9"url ="~\9.aspx"> <siteMapNode title="部门维护" url="~\DeptForms\frmMain.htm" description="部门维护"/> <siteMapNode title="用户管理"url="~\DeptForms\frmUsers.htm" description="用户管理"/> .. </siteMapNode></siteMapNode></siteMap>
比如:target="_parent"disenable="true"startIndex="1" AdminIndex。。。都是扩展的属性,用于一些控制逻辑的实现
2、根据输出一级菜单控制HTML及脚本
当然B/S系统实现OUTLOOK风格的菜单一定也是一些HTML、样式表、脚本来实现的。实现这一功能开发要做的事情是,根据sitemap的一级菜单设置输出相应的HTML。
[代码参考]
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" ><!--disenable为true表示显示全部菜单,如果没权限显示不可用,如果为false表示没有权限则移除--><siteMapNode title="主页" url="Newmain.aspx" target="_parent" disenable="true" startIndex="1"AdminIndex="9"> <siteMapNode title="我的桌面" img="skins/2004/images/icon/desktop.gif"menuIndex="1"url ="~\1.aspx"> <siteMapNode title="待办事项" url="~\Forms\frmContent.aspx" description="待办事项"targeturl="" /> <siteMapNode title="我登记事件" url="~\Forms\frmWaittingContent.aspx?TypeContent=MyReg" description="我登记事件"/> <siteMapNode title="出差授权" url="~\Forms\FrmAgentSet.aspx" description="出差授权"/> </siteMapNode> . <siteMapNode title="系统管理" img="skins/2004/images/icon/sKms.gif"menuIndex="9"url ="~\9.aspx"> <siteMapNode title="部门维护" url="~\DeptForms\frmMain.htm" description="部门维护"/> <siteMapNode title="用户管理"url="~\DeptForms\frmUsers.htm" description="用户管理"/> .. </siteMapNode></siteMapNode></siteMap> 比如:target="_parent"disenable="true"startIndex="1" AdminIndex。。。都是扩展的属性,用于一些控制逻辑的实现 2、根据输出一级菜单控制HTML及脚本当然B/S系统实现OUTLOOK风格的菜单一定也是一些HTML、样式表、脚本来实现的。实现这一功能开发要做的事情是,根据sitemap的一级菜单设置输出相应的HTML。 [代码参考] protected void Page_Load(object sender, System.EventArgs e) { // 在此处放置用户代码以初始化页面 if (!Page.IsPostBack) { LoadMenusHtml(); } } private void LoadMenusHtml() { string strTitle = ""; string strMenus = ""; string strUserName = Session["UserName"].ToString().Trim(); Epower.ITSM.SqlDAL.UIMethod ui = new Epower.ITSM.SqlDAL.UIMethod(); ui.GetMenuHtml(Session["UserName"].ToString(), (long)Session["UserID"], ref strTitle, ref strMenus); litMenuTitle.Text = strTitle; litMenus.Text = strMenus; }/**//// <summary> /// 获取普通用户菜单HTML /// </summary> /// <param name="lngUserID"></param> /// <param name="strHeader"></param> /// <param name="strMens"></param> publicvoid GetMenuHtml(string strUserName,long lngUserID,ref string strHeader,ref string strMens) { StringBuilder sb = new StringBuilder(""); StringBuilder sbTitle = new StringBuilder(""); bool isManager = UserDP.IsManager(lngUserID); string strStartIndex = SiteMap.RootNode["startIndex"]; string strAdminIndex = SiteMap.RootNode["AdminIndex"]; string strNodeIndex = ""; if (strAdminIndex == strStartIndex) { //如果相同则取第一个 实际设置中几乎不太可能设置成一个 strStartIndex = "1"; } SiteMapNodeCollection childCollection = SiteMap.RootNode.ChildNodes; sb.Append(@"<table class=""navContent"" height=""100%"" cellSpacing=""0"" cellPadding=""0"" width=""96%"" align=""center"" border=""0""> <tr> <td vAlign=""top"" bgColor=""#ffffff"" height=""100%""><iframe id=""frameColumnNav"" style=""WIDTH: 100%; HEIGHT: 100%"" this.blur();"" border=""0"" name=""frameColumnNav"" marginWidth=""0"" marginHeight=""0"" src=""submenu.aspx?username=" + strUserName + "&mid=" + strStartIndex + @""" frameBorder=""0"" scrolling=""auto""></iframe> </td> </tr> <tr> <td style=""CURSOR: hand"" setNavMenu();"" vAlign=""bottom"" align=""center"" background=""skins/2004/images/bg_middle1_main.gif"" height=""5""><IMG height=""5"" src=""skins/2004/images/bg_middle1_button.gif""></td> </tr> <tr id=""navMenu"" name=""navMenu""> <td vAlign=""bottom"" bgColor=""#ffffff"" height=""0px""> <table id=""tableNAV"" cellSpacing=""0"" cellPadding=""0"" width=""100%"" align=""center"" border=""0"" name=""tableNAV"">"); int i = 1; foreach (SiteMapNode node in childCollection) { strNodeIndex = node["menuIndex"]; if (isManager == true || strNodeIndex != strAdminIndex) { sb.Append(@"<tr><td align=""left"" setNavMenuBGMove(" + i.ToString() + @")"" onmouseout=""setNavMenuBGOut(" + i.ToString() + @")"" class=""" + (strStartIndex == strNodeIndex ? "navColumnLight" : "navColumnDark") + @""" id=""navMenu" + i.ToString() + @""" style=""height: 25px"" navTitleDiv.innerHTML='" + node.Title + @"';document.all.frameColumnNav.src='submenu.aspx?username=" + strUserName + "&mid=" + strNodeIndex + @"'; setNavMenuBG(" + i.ToString() + @")"" ><IMG src=""" + node["img"] + @""" width=""16"" align=""absMiddle""> <A href=""#"">" + node.Title + @"</A> </td> </tr>"); if (strStartIndex == strNodeIndex) { //因为 开始ID 不可能与 管理ID相同,因此 此句一定能执行得到 sbTitle.Append(@"<div class=""navTitle"" id=""navTitleDiv"" name=""navTitleDiv"">" + node.Title + @"</div>"); } i++; } } sb.Append(@"</table> <table id=""tableNavIndex"" cellSpacing=""0"" cellPadding=""0"" width=""100%"" border=""0"" name=""tableNavIndex""> <tr> <td class=""navColumnDark"" id=""navMenuIndex"" style=""DISPLAY: none"" height=""25""> <div align=""center"" width=""100%""> "); i = 1; foreach (SiteMapNode node in childCollection) { strNodeIndex = node["menuIndex"]; if (isManager == true || strNodeIndex != strAdminIndex) { sb.Append(@"<A navTitleDiv.innerHTML='" + node.Title + @"';document.all.frameColumnNav.src='submenu.aspx?username=" + strUserName + "&mid=" + strNodeIndex + @"';setNavMenuBG(" + i.ToString() + @")"" href=""#""><IMG title=""" + node.Title + @""" src=""" + node["img"] + @""" width=""16"" align=""absMiddle"" border=""0""></A> "); i++; } } sb.Append(@"</div> </td> </tr> </table> </td> </tr> </table>"); strHeader = sbTitle.ToString(); strMens = sb.ToString(); }
3、权限控制
在大部分国内的系统用户,是希望能在菜单上控制到权限的,权限的实现是跟某个具体的系统管理模块紧密相关的。Sitemap提供的权限控制跟微软提供的权限模块紧密梆定但不一定能满足国内系统的管理需求。
需要在sitemap上实现自己的权限控制代码。
[代码参考]
/**//// <summary> /// 如果为false,表示设置为没有权限的菜单移除 /// </summary> /// <param name="strID"></param> /// <param name="item"></param> public void CheckNodeRight(string strID, TreeNode item, Hashtable htAllRights, TreeView TreeView1) { long OperatorID = 0; try { OperatorID = long.Parse(strID); } catch { } if (OperatorID == 0) return; RightEntity re = (RightEntity)htAllRights; if (re == null) return; else { if (re.CanRead == false) { //移除菜单项 TreeNode pitem = item.Parent; if (pitem != null) { pitem.ChildNodes.Remove(item); } else { TreeView1.Nodes.Remove(item); } } } }
4、利用缓存技术进行优化
因为菜单页面的访问是非常频繁的,但用户和权限的变化频率比较小,对于大规模访问的系统来说,不要忘记利用缓存技术进行优化。 由于页面的输出跟用户有关,因此利用visual studio 2005的页面缓存功能就可以非常简单的实现了。
在菜单页面上加上标记:
<%@ OutputCache Duration="300000" VaryByParam="*"%> 即可,因为URL上已经将参数区别了。系统会自动根据参数不同缓存相应的版本。
5、配置sitemap实现功能
以上开发完成后,通过配置sitemap即可实现OUTLOOK风格的菜单了。还可以复制到其它系统中重复利用,实现重用的价值。
页:
[1]