超级简单:一个横向ASP.NET Menu控件

    几个星期前,开始了一个ASP.NET Web应用程序,需要一个简单的横向的带子菜单的Menu控件。将Menu控件拖拽到一个页面上时,我就决定使用ASP.NET的Menu控件。这个控件很简单,但该控件不提供访问的key和支持菜单窗体的target。我把这些功能放在一起将如何去实现:

1、包含accesskey属性

2、包含target属性

3、包含Site Map Path

超级简单:一个横向ASP.NET Menu控件

 

这是项目工程的结构,欢迎你下载这个Demo。

超级简单:一个横向ASP.NET Menu控件

 

     首先,添加一个Site Map 到我们的website工程。打开web.sitemap文件,添加你的导航数据和导航结构。为了强调一个菜单标题的某些特征,我们可以使用HTML下划线记 (<u></u>)。为了正确地解析XML,我们必须用 & lt;取代小于号(<)。每个siteMapNode包含一个accesskey 和target属性值。

Listing 1:

代码
< siteMapNode >
      
< siteMapNode  url ="Default.aspx"  
         title
="& lt;u>H& lt;/u>ome"  
         description
="Home"  
         accesskey
="H"   />
      
< siteMapNode  url ="~/Views/Menu1.aspx"  
                   title
="& lt;u>M& lt;/u>enu1"   
                   description
="Menu1"  accesskey ="M"   />
        
< siteMapNode  url ="~/Views/Menu2.aspx"  
                     title
="M<u>e</u>nu2"  
                     description
="Menu2"  accesskey ="E"   />
    
    
< siteMapNode  url ="~/Views/Menu3.aspx"  
                 title
="Me<u>n</u>u3"  
                 description
="Menu3"  
                 accesskey
="N"  target ="_blank"   />
        
    
< siteMapNode  url ="~/Views/Menu4.aspx"  
                 title
="Men<u>u</u>4"  
                 description
="Menu4"  accesskey ="U" >
      
< siteMapNode  url ="~/Views/Menu4Sub1.aspx"  
                   title
="Menu4<u>S</u>ub1"  
                   description
="Menu4Sub1"  
                   accesskey
="S"   />
      
< siteMapNode  url ="~/Views/Menu4Sub2.aspx"  
                   title
="Menu4Su<u>b</u>2"  
                   description
="Menu4Sub2"  
                   target
="_blank"  accesskey ="B"   />
    
</ siteMapNode >
……
….
  
</ siteMapNode >
</ siteMap >

      添加一个Master Pag到我们的website项目中,拖一个SiteMapDataSource控件到页面上,接着拖一个Menu控件,Menu控件包含在一个div里面,menu每个属性都能在这里被找到,

设置 staticdisplaylevels ="2"orientation="Horizontal"来横向的显示menu控件。我们可以使用内联样式表或放置在一个外部文件中的CSS样式。在本例中,CSS样式位于style.css文件。

Listing 2:

代码
< asp:SiteMapDataSource  id ="MenuSource"  runat ="server"   />
< div  class ="background" >
  
< asp:menu  id ="NavigationMenu"  CssClass ="NavigationMenu"   
        staticdisplaylevels
="2"  DynamicHorizontalOffset ="1"
        staticsubmenuindent
="1px"  MaximumDynamicDisplayLevels ="4"
        orientation
="Horizontal"    
        DynamicPopOutImageUrl
="~/Images/right-arrow.gif"  
        StaticPopOutImageUrl
="~/Images/drop-arrow.gif"
        datasourceid
="MenuSource"     
        runat
="server"  Height ="30px" >

        
< staticmenuitemstyle  ItemSpacing ="10"  
                    CssClass
="staticMenuItemStyle" />
        
< statichoverstyle  CssClass ="staticHoverStyle"   />
       
< StaticSelectedStyle  CssClass ="staticMenuItemSelectedStyle" />  
        
< DynamicMenuItemStyle  CssClass ="dynamicMenuItemStyle"   />       
        
< dynamichoverstyle  CssClass ="menuItemMouseOver"   />
        
< DynamicMenuStyle  CssClass ="menuItem"   />
       
< DynamicSelectedStyle  CssClass ="menuItemSelected"   />
     
       
< DataBindings >         
             
< asp:MenuItemBinding  DataMember ="siteMapNode"  
                    NavigateUrlField
="url"  TextField ="title"   
                    ToolTipField
="description"   />
        
</ DataBindings >

      
</ asp:menu >
</ div >

 拖一个SiteMapPath 控件到页面上。这个控件的目的是显示导航路径和显示用户当前页的位置。请看看Listing 3。

 Listing 3:

代码
< div  id ="e" >
       
< asp:SiteMapPath  ID ="SiteMapPath1"  runat ="server"  
                RenderCurrentNodeAsLink
="true"  
                CssClass
="currentNodeStyle"
            PathSeparator
=" >> " >
            
< PathSeparatorStyle  ForeColor ="#5D7B9D"  CssClass ="currentNodeStyle"   />
            
< CurrentNodeStyle  ForeColor ="#333333"  CssClass ="currentNodeStyle"   />
            
< NodeStyle  ForeColor ="#7C6F57"   CssClass ="currentNodeStyle"    />
            
< RootNodeStyle   ForeColor ="#5D7B9D"  CssClass ="currentNodeStyle"    />
    
</ asp:SiteMapPath >  
</ div >

    在Page_Load事件中包括MenuItemDataBound和SiteMapResolve事件处理程序。前者的目的是插入target的属性值,在Meun呈现或者显示之前,为菜单项创造accesskey。后者是修改的SiteMapPath控件显示的文本。

 

NavigationMenu.MenuItemDataBound  +=  
     
new  MenuEventHandler(NavigationMenu_MenuItemDataBound);
SiteMap.SiteMapResolve 
+=  
     
new  SiteMapResolveEventHandler(SiteMap_SiteMapResolve);

    下面显示的是该NavigationMenu_MenuItemDataBound实现的方法。在Menu控件中的菜单项绑定数据时,触发MenuItemDataBound事件发生。话虽如此,这将通过循环SiteMapNode来寻找accesskeytarget属性。每一个target属性与菜单项关联,我们可以用target属性值来设置目标窗口。

 

代码
void  NavigationMenu_MenuItemDataBound( object  sender, MenuEventArgs e)
{
    SiteMapNode node 
=  (SiteMapNode)e.Item.DataItem;
   
    
// set the target of the navigation menu item (blank, self, etc...)
     if  (node[ " target " !=   null )
    {
        e.Item.Target 
=  node[ " target " ];
    }
    
// create access key button
     if  (node[ " accesskey " !=   null )
    {
        CreateAccessKeyButton(node[
" accesskey " as   string , node.Url);
    }
}

    要获得accesskey,将在母版页上添加一个Panel控件和一个重定向到指定的一个网页的JavaScript函数。请看Listing 6

 Listing 6:

< asp:Panel ID = " AccessKeyPanel "  runat = " server "   />
< script type = " text/javascript " >
 function navigateTo(url) {
    window.location 
=  url;
 }
</ script >

  下面是CreateAccessKeyButton方法的实现。动态的创建一个HtmlButton控件,给它添加一个onclick事件。设置style.left样式属性为-255px来隐藏这个控件。

代码
// create access key button
void  CreateAccessKeyButton( string  ak,  string  url)
{
    HtmlButton inputBtn 
=   new  HtmlButton();
    inputBtn.Style.Add(
" width " " 1px " );
    inputBtn.Style.Add(
" height " " 1px " );
    inputBtn.Style.Add(
" position " " absolute " );
    inputBtn.Style.Add(
" left " " -2555px " );
    inputBtn.Style.Add(
" z-index " " -1 " );
    inputBtn.Attributes.Add(
" type " " button " );
    inputBtn.Attributes.Add(
" value " "" );
    inputBtn.Attributes.Add(
" accesskey " , ak);
    inputBtn.Attributes.Add(
" onclick " " navigateTo(' "   +  url  +   " '); " );
    AccessKeyPanel.Controls.Add(inputBtn);
}

   当CurrentNode属性被访问时,SiteMap.SiteMapResolve事件被触发。这将调用递归的ReplaceNodeText方法,来替换HTML下划线标记 。请看Listing 8

 Listing 8:

代码
SiteMapNode SiteMap_SiteMapResolve( object  sender, SiteMapResolveEventArgs e)
{
    SiteMapNode currentNode 
=  SiteMap.CurrentNode.Clone( true );
    SiteMapNode tempNode 
=  currentNode;
    tempNode 
=  ReplaceNodeText(tempNode);

    
return  currentNode;
}

// remove <u></u> tag recursively
internal  SiteMapNode ReplaceNodeText(SiteMapNode smn)
{
    
// current node
     if  (smn  !=   null   &&  smn.Title.Contains( " <u> " ))
    {
        smn.Title 
=  smn.Title.Replace( " <u> "
                       
"" ).Replace( " </u> " "" );
    }

    
// parent node
     if  (smn.ParentNode  !=   null )
    {
        
if  (smn.ParentNode.Title.Contains( " <u> " ))
        {
            SiteMapNode gpn 
=  smn.ParentNode;
            smn.ParentNode.Title 
=  smn.ParentNode.Title.Replace(
              
" <u> " "" ).Replace( " </u> " "" );
            smn 
=  ReplaceNodeText(gpn);
        }
    }
    
return  smn;
}

    

     在移动设备上,悬停菜单似乎无法显示。为了解决这个问题,我使用一个TreeView控件并设置其Visible属性为false。默认情况下,这个控件展开它所有的节点的。这将需要对上述问题进行处理。如果请求浏览是一个移动设备,在后台代码中,隐藏的菜单控件和显示TreeView控件。

protected   void  Page_Load( object  sender, EventArgs e)
{
    
if  (Request.Browser.IsMobileDevice)
    {
        NavigationMenu.Visible 
=   false ;
        NavigationTreeView.Visible 
=   true ;
    }
}

     当我在IE 8中测试菜单时,悬停菜单也没有正确呈现。为了克服这个问题, 我们设置DynamicMenuStyle z-index 为200。子菜单在谷歌浏览器不能运行。经过一番研究,我找到了解决的办法。见下面。

代码
protected   void  Page_Load( object  sender, EventArgs e)
{
    
if  (Request.UserAgent.IndexOf( " AppleWebKit " >   )
    {
        Request.Browser.Adapters.Clear();
        NavigationMenu.DynamicMenuStyle.Width 
=  Unit.Pixel( 120 );
    }
}

     如果您发现任何错误或对内容有不同的意见,请给我留言,我会与你一起加以纠正。

效果:http://download.ysatech.com/ASP-NET-Menu-Control/

代码:/Files/zhuqil/MenuControl.zip

原文:http://www.codeproject.com/KB/webforms/Horizontal-Menu-Control.aspx


原文链接: http://www.cnblogs.com/zhuqil/archive/2009/12/22/1629492.html

你可能感兴趣的:(超级简单:一个横向ASP.NET Menu控件)