您的位置:首页 > 编程语言 > ASP

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

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

1、包含
accesskey属性


2、包含target
属性

3、包含Site Map Path



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



首先,添加一个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来寻找accesskey
target
属性。每一个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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: