简洁的Asp.net菜单控件

asp.net自带的菜单控件采用的table和javascript,导致生成的大量的html,同时在很多浏览器中都无法显示出子菜单,也只能在IE中能显示出来。

本文介绍的菜单控件采用的css 和ul list来显示菜单,生成的html小,无需javascript支持,对大部分的浏览器都支持,除ie6要单独修改css也可以使其支持。

通过本文可以了解asp.net 控件的开发,及Composite设计模式的实际运用。

 采用Composite设计模式设计菜单类:

MenuCompositeitem类

namespace  Ruinet.Controls
{
  [Serializable()]
  
public   class  MenuCompositeItem
  {
    
private  List < MenuCompositeItem >  _children  =   new  List < MenuCompositeItem > ();
    
private   string  _text;
    
private   string  _link;
    
private   string  _target;

    
///   <summary>
    
///  菜单项
    
///   </summary>
    
///   <param name="text"> 菜单名 </param>
    
///   <param name="link"> 链接 </param>
     public  MenuCompositeItem( string  text,  string  link)
    {
      
this ._text  =  text;
      
this ._link  =  link;
    }
    
///   <summary>
    
///  菜单项
    
///   </summary>
    
///   <param name="text"> 菜单名 </param>
    
///   <param name="link"> 链接 </param>
    
///   <param name="target"> 跳转目标 </param>
     public  MenuCompositeItem( string  text,  string  link,  string  target)
    {
      
this ._text  =  text;
      
this ._link  =  link;
      
this ._target  =  target;
    }

    
///   <summary>
    
///  设置或获取菜单名
    
///   </summary>
     public   string  Text
    {
      
get  {  return  _text; }
      
set  { _text  =  value; }
    }

    
///   <summary>
    
///  设置或获取链接
    
///   </summary>
     public   string  Link
    {
      
get  {  return  _link; }
      
set  { _link  =  value; }
    }
    
///   <summary>
    
///  跳转目标
    
///   </summary>
     public   string  Target
    {
      
get  {  return  _target; }
      
set  { _target = value; }
    }

    
///   <summary>
    
///  设置或获取子菜单
    
///   </summary>
     public  List < MenuCompositeItem >  Children
    {
      
get  {  return  _children; }
      
set  { _children  =  value; }
    }
  }

MenuComposite类

namespace  Ruinet.Controls
{
  [DefaultProperty(
" Menu " )]
  [ToolboxData(
" <{0}:MenuComposite runat=server></{0}:MenuComposite> " )]
  
public   class  MenuComposite : WebControl
  {
    
///   <summary>
    
///  设置获取选择的菜单
    
///   </summary>
    [Bindable( true )]
    [DefaultValue(
"" )]
    [Localizable(
true )]
    
public   string  SelectedMenuText
    {
      
get
      {
        String s 
=  (String)ViewState[ " SelectedMenuText " ];
        
return  ((s  ==   null ?  String.Empty : s);
      }

      
set
      {
        ViewState[
" SelectedMenuText " =  value;
      }
    }

    
///   <summary>
    
///  获取和设置菜单项从ViewState
    
///   </summary>
    [Bindable( true )]
    [DefaultValue(
null )]
    [Localizable(
true )]
    
public  MenuCompositeItem MenuItems
    {
      
get
      {
        
return  ViewState[ " MenuItems " as  MenuCompositeItem;
      }

      
set
      {
        ViewState[
" MenuItems " =  value;
      }
    }

    
///   <summary>
    
///  呈现菜单结构
    
///   </summary>
    
///   <param name="output"> HTML输出流 </param>
     protected   override   void  RenderContents(HtmlTextWriter output)
    {
      MenuCompositeItem root 
=   this .MenuItems;

      output.Write(
@" <div class=""navmenu""> " );
      output.Write(
@"     <ul> " );

      
for  ( int  i  =   0 ; i  <  root.Children.Count; i ++ )
      {
        RecursiveRender(output, root.Children[i]);
      }
      output.Write(
@"     </ul> " );
      output.Write(
@" </div> " );
    }

    
///   <summary>
    
///  递归输出菜单项
    
///   </summary>
    
///   <param name="output"> HTML输出流 </param>
    
///   <param name="item"> 菜单项. </param>
    
///   <param name="depth"> Indentation depth. </param>
     private   void  RecursiveRender(HtmlTextWriter output, MenuCompositeItem item)
    {
      output.Write(
" <li> " );
      
if  ( string .IsNullOrEmpty(item.Target)) // 为空不设置跳转目标
      {
        output.Write(
@" <a href="" "   +  item.Link  +   @" ""> " );
      }
      
else
      {
        output.Write(
@" <a href="" "   +  item.Link  +   @" "" target= "" "   +  item.Target  +   @" ""> " );
      }
      
if  (item.Text  ==  SelectedMenuText)   // 选中的菜单
      {
        output.Write(
@" <span class=""selected""> " );
        output.WriteLine(item.Text);
        output.WriteLine(
" </span> " );
      }
      
else
      {
        output.Write(item.Text);
      }

      output.Write(
" </a> " );

      
if  (item.Children.Count  >   0 )
      {
        output.WriteLine();
        output.Write(
" <ul> " );
        
for  ( int  i  =   0 ; i  <  item.Children.Count; i ++ )
        {
          RecursiveRender(output, item.Children[i]);
        }
        output.Write(
" </ul> " );
      }
      output.Write(
" </li> " );
    }
  }
}

 在页面中使用

添加对控件的引用后就可以直接在“工具箱”-》Controls组件中 看到MenuComposite组件

再就可以像其他asp.net 控件一样使用

使用:

 MenuCompositeItem root  =   new  MenuCompositeItem( " root " null );
    MenuCompositeItem menu01 
=   new  MenuCompositeItem( " menu01 " , ResolveUrl( " ~/Default.aspx " ));
    MenuCompositeItem menu02 
=   new  MenuCompositeItem( " menu02 " , ResolveUrl( " ~/Default.aspx " ));
    MenuCompositeItem menu03 
=   new  MenuCompositeItem( " menu03 " , ResolveUrl( " ~/Default.aspx " ));
    MenuCompositeItem menu04 
=   new  MenuCompositeItem( " menu04 " , ResolveUrl( " ~/Page04.aspx " ));
    MenuCompositeItem menu05 
=   new  MenuCompositeItem( " menu05 " , ResolveUrl( " ~/Default.aspx " ));

    MenuCompositeItem menu01_01 
=   new  MenuCompositeItem( " menu01-01 " , ResolveUrl( " ~/Default.aspx " ));
    MenuCompositeItem menu01_02 
=   new  MenuCompositeItem( " menu01-02 " , ResolveUrl( " ~/Page01-02.aspx " ));
    MenuCompositeItem menu01_03 
=   new  MenuCompositeItem( " menu01-03 " , ResolveUrl( " ~/Default.aspx " ));
    MenuCompositeItem menu01_04 
=   new  MenuCompositeItem( " menu01-04 " , ResolveUrl( " ~/Default.aspx " ));
    menu01.Children.Add(menu01_01);
    menu01.Children.Add(menu01_02);
    menu01.Children.Add(menu01_03);
    menu01.Children.Add(menu01_04);


    MenuCompositeItem menu02_01 
=   new  MenuCompositeItem( " menu02-01 " , ResolveUrl( " ~/Default.aspx " ));
    MenuCompositeItem menu02_02 
=   new  MenuCompositeItem( " menu02-02 " , ResolveUrl( " ~/Default.aspx " ),  " menu02-02 " );
    menu02.Children.Add(menu02_01);
    menu02.Children.Add(menu02_02);


    MenuCompositeItem menu04_01 
=   new  MenuCompositeItem( " menu04-01 " , ResolveUrl( " ~/Default.aspx " ));
    MenuCompositeItem menu04_02 
=   new  MenuCompositeItem( " menu04-02 " , ResolveUrl( " ~/Page04-02.aspx " ),  " _blank " );
    menu04.Children.Add(menu04_01);
    menu04.Children.Add(menu04_02);

    root.Children.Add(menu01);
    root.Children.Add(menu02);
    root.Children.Add(menu03);
    root.Children.Add(menu04);
    root.Children.Add(menu05);

    TheMenuComposite.MenuItems 
=  root;

此时生成的编译运行后会生成一个没有样式Ul list ,效果如下:

简洁的Asp.net菜单控件_第1张图片  

因此要生成可显示和隐藏的菜单项,关键在css的设置上,开始时将二级子菜单设置为隐藏visibility: hidden;

同时定义li的hover事件,li:hover时:自菜单的 visibility要改为visible; 大致原理是这样,当然还有注意菜单项的位置

一级菜单float:left;使其能水平显示。

CSS定义如下:

.navmenu *
{
    margin
:  0 ;
    padding
:  0 ;
}
.navmenu
{
    border
:  #000 1px solid ;
    height
:  25px ;
}
.navmenu li
{
    
/* 水平菜单 */
    float
:  left ;
    list-style
:  none ;
    position
:  relative ;
}
.navmenu a
{
    display
:  block ;
    font-size
:  12px ;
    height
:  24px ;
    width
:  100px ;
    line-height
:  24px ;
    background-color
:  #CDEB8B ;
    color
:  #0000ff ;
    text-decoration
:  none ;
    text-align
:  center ;
    border-left
:  #36393D 1px inset ;
    border-right
:  #36393D 1px inset ;
    border-bottom
:  #36393D 1px inset ;
}
/* 单独设置一级菜单样式 */
.navmenu > ul > li > a
{
    font-size
:  11px ;
    font-weight
:  bold ;
}
.navmenu a:hover
{
    background
:  #369 ;
    color
:  #fff ;
}
/* 新增的二级菜单部分 */
.navmenu ul ul
{
    visibility
:  hidden ;   /* 开始时是隐藏的 */
    position
:  absolute ;
    left
:  0px ;
    top
:  24px ;
}
.navmenu ul li:hover ul, .navmenu ul a:hover ul
{
    visibility
:  visible ;
}
.navmenu ul ul li
{
    clear
:  both ;   /* 垂直显示 */
    text-align
:  left ;
}
/* 选中菜单项 */
.navmenu .selected
{
    padding-left
: 15px ;
    background-position-x
: 0px ;
    background-image
:  url(./res/selected.gif) ;
    background-repeat
:  no-repeat ;
    text-decoration
: underline ;
}

定义CSS后的效果如下:

简洁的Asp.net菜单控件_第2张图片

到此菜单控件已完成。已测试过可以在IE7,IE8,Chrome,Firefox中正常显示,在IE6显示可能会有问题,可以参考纯CSS多级菜单 进行修改,

本文的CSS显示部分参考了此文的介绍。

 附上完整代码,如需要可自行下载修改:/Files/ruinet/WebMenu.zip

 

 

你可能感兴趣的:(简洁的Asp.net菜单控件)