大型的企业级网站,可能有成百上千个网页,导航变得十分重要。
好的导航系统能够方便用户在多个页面间来回浏览,增加了应用程序的可交互性。
ASP.NET提供了内置的导航技术,让开发人员创建站点导航变得轻松。
本章内容有:
用于定义站点结构。
ASP.NET中的站点地图导航技术由以下三个文件组成:
站点地图是一个名为Web.sitemap的XML文件。
ASP.NET站点地图的基本原理:
ASP.NET内置了一个成为站点地图提供者的提供者类,名为XmlSiteMapProvider,该提供者能够从XML中获取信息。XmlSiteMapProvider将查找位于应用程序
根目录中的Web.sitemap文件,然后提取该文件中的站点地图数据并创建相应的SiteMap对象,SiteMapDataSource将使用这些SiteMap对象向导航控件提供导航信息。
Web.site必须位于应用程序目录下,并且不能更改为其他名称。
这里要建的导航结构为:
接下来我们详细记录建立站点导航的过程:VS2019
(1)新建web项目
(2)新建要调用的产品、服务web窗体页面
这里需要注意的是,现在项目上右键添加两个文件夹,分别命名为Products、Services,然后分别在两个文件夹鼠标右键建立Web窗体页面。
(3)新建一个首页Web窗体页面,命名为Default.aspx
(4)项目右键添加-站点地图,不要改名字!!!Web.sitemap
这个名称是固定的!!!
(5)接下来是各个页面中的代码:
Default.aspx页面
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="SiteMap3.Default" %> 首页
HardwareProduct.aspx页面
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="HardwareProduct.aspx.cs" Inherits="SiteMap3.Products.HardwareProduct" %> 硬件产品
SoftwareProduct.aspx页面
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="SoftwareProduct.aspx.cs" Inherits="SiteMap3.Products.SoftwareProduct" %> 软件产品
ServiceCenter.aspx页面
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ServiceCenter.aspx.cs" Inherits="SiteMap3.Services.ServiceCenter" %> 服务中心
ServiceNote.aspx页面
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ServiceNote.aspx.cs" Inherits="SiteMap3.Services.ServiceNote" %> 服务须知
Web.sitemap站点地图页面
运行结果:
SiteMapPath控件已经在上面的案例中使用,是在站点地图结构、结构中对应的页面做好以后,分别在各个页面的窗体中加入SiteMapPath控件。
一个页面中的添加如下:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="SiteMap3.Default" %> 首页
接下来介绍一些SiteMapPath控件的属性:
属性名称 | 属性描述 |
---|---|
ParentLevelsDisplay | 允许显示的父节点的数量,默认情况下SiteMapPath控件显示所有的父节点 |
PathDirection | 允许反转SiteMapPath控件显示的链接的顺序,可选值有RootToCurrent,这是默认值,表示从根父级显示到当前级。CurrentToRoot表示从当前页面显示到根级 |
PathSeparator | 指定用于分隔节点的字符串,默认的是“>”,可以指定任意的字符 |
RenderCurrentNodeAsLink | 是否允许将SiteMapPath描述的当前节点呈现为链接 |
ShowToolTips | 是否允许显示工具提示 |
SiteMapProvider | 允许SiteMapPath控件指定其他的站点地图提供者 |
SiteMapPath提供了很多的样式控制选项,允许对其外观进行精细的控制。除此以外,还可以对SiteMapPath控件应用模板来自定义外观,以下列出所有的样式及模板。
样式 | 模板 | 说明 |
---|---|---|
NodeStyle | NodeTemplate | 所有除了根节点和当前节点的节点样式 |
CurrentNodeStyle | CurrentNodeTemplate | 当前节点的样式 |
RootNodeStyle | RootNodeTemplate | 根节点的样式 |
PathSeparatorStyle | PathSeparatorTemplate | 节点之间分隔符的样式 |
使用SiteMapPath控件,开发人员不需要编写代码就可以在页面中添加站点导航,也可以对站点地图进行编程操作。ASP.NET公开了一个反应站点地图结构的静态
的SiteMapPath对象,该对象公开SiteMapNode对象的集合,用于表示站点中每个节点。
SiteMap对象中所有成员都是静态的,因此无需实例化SiteMap对象。SiteMap自身只具有两个与导航相关的属性:
而SiteMap对象的成员SiteMapNode对象具有多个与导航相关的属性:
属性 | 属性说明 |
---|---|
ParentNode | 返回当前节点的上一级节点,包含当前节点。如果是根节点,这个属性返回一个null引用 |
ChildNode | 返回所有当前节点的子节点集合。可以通过检查HasChildNodes属性来判断当前节点是否有子节点 |
PreviousSibling | 返回相同等级的上一个节点,如果不存在则返回null |
NextSibling | 返回相同等级的下一个节点,如果不存在则返回null |
在首页中加入一个label控件,用来显示通过SiteMap对象获取的节点信息:(需要注意,之前加的那个SiteMapPath控件的名称不能是SiteMap,不然就会和SiteMap类对象产生二义性,获取不到属性!!!!!!!!!!!!!!)
代码中加入遍历站点地图结构的节点信息代码:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="SiteMap3.Default" %> 首页
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace SiteMap3 { public partial class Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { // 获取所有的站点地图节点信息 lbTree.Text = "当前节点信息:
"; lbTree.Text += SiteMap.CurrentNode.Title + "
"; lbTree.Text += SiteMap.CurrentNode.Description + "
"; if (SiteMap.CurrentNode.NextSibling != null) { lbTree.Text += "同级节点的下一个节点信息:" + "
"; lbTree.Text += SiteMap.CurrentNode.NextSibling.Title + "
"; lbTree.Text += SiteMap.CurrentNode.NextSibling.Description + "
"; } } } }
运行结果:运行结果是在软件产品页面中加入了遍历的结果!!!!!!
URL地址映射就是在浏览器中给实际不想显示的URL地址穿上一个马甲,因此从实际URL映射到另一个对外显示的URL地址。
ASP.NET可以在web.config配置文件中使用块来配置URL地址映射。
下面是一个简单的URL地址映射的示例代码:
但是ASP.NET中的地址映射有很大的不足,就是只能硬编码地址,导致配置文件太大。网上已经有解决方法。
TreeView就是不论是操作系统,还是应用程序的分支点目录。
TreeView支持以下功能:
本节将讨论使用TreeView控件开发ASP.NET应用程序的导航功能。
新建网站,添加一个TreeView控件。
在设计模式下,拖一个TreeView控件,弹出设置框,自动套用格式下很多可以选择的树状图形式。
选择数据源,后面会讲定义数据源,以及绑定数据源:
如果已经添加了节点,可以编辑节点:
自定义行图标样式:
选择显示行或者不显示行,就是连线:
经过初始化的设置,回到标记模式中,看到已经增添了一些属性:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="TreeView.Default" %>
我们来手动输入一些属性,建立一些节点:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="TreeView.Default" %>
运行结果:
TreeView的属性:
属性 | 属性说明 |
---|---|
Tetx | 显示在节点中的文本 |
ToolTip | 当鼠标悬停在节点上面时显示的提示信息 |
Value | 保存节点的值,节点的值是一种不可见的附件数据,用于保存节点的附加信息 |
NavigateUrl | 当单击节点时,节点所链接的URL路径 |
Target | 如果NavigateUrl被设置,用这个属性设置打开的目标窗口 |
ImageUrl | 显示在节点前面的图像URL |
ImageToolTip | 显示在节点前面的图片的提示信息 |
编程方式给TreeView添加节点:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace TreeView { public partial class Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { // 以编程的方式给TreeView对象添加节点 // 新建一个TreeNode对象 TreeNode rootNode = new TreeNode("软件开发系列图书"); // 将rootNode对象添加到TreeView对象的Nodes节点,这是必须的,否则TreeView将不会呈现节点 TreeView1.Nodes.Add(rootNode); // 继续添加子节点 TreeNode childNode = new TreeNode(".NET版"); childNode.ChildNodes.Add(new TreeNode("C# 2008程序设计")); childNode.ChildNodes.Add(new TreeNode("ASP.NET从入门到精通")); childNode.ChildNodes.Add(new TreeNode("SilverLight2.0开发人员指南")); childNode.ChildNodes.Add(new TreeNode("WCF程序设计")); rootNode.ChildNodes.Add(childNode); } } }
运行结果:
首先给项目中加入之前写的这个Web.sitemap站点导航文件。
再加入一个TreeView控件:
窗体页面设计代码:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="TreeView.Default" %>
后台代码:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace TreeView { public partial class Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { // 以编程的方式给TreeView对象添加节点 //====================================第一种:直接编程添加TreeView节点================================================ // 新建一个TreeNode对象 TreeNode rootNode = new TreeNode("软件开发系列图书"); // 将rootNode对象添加到TreeView对象的Nodes节点,这是必须的,否则TreeView将不会呈现节点 TreeView1.Nodes.Add(rootNode); // 继续添加子节点 TreeNode childNode = new TreeNode(".NET版"); childNode.ChildNodes.Add(new TreeNode("C# 2008程序设计")); childNode.ChildNodes.Add(new TreeNode("ASP.NET从入门到精通")); childNode.ChildNodes.Add(new TreeNode("SilverLight2.0开发人员指南")); childNode.ChildNodes.Add(new TreeNode("WCF程序设计")); rootNode.ChildNodes.Add(childNode); //======================================第二种,通过编程绑定站点地图信息添加TreeView节点============================================== // 以下是TreeView2的使用导航功能的代码 // 初始化根节点 TreeNode node = new TreeNode("首页"); // 调用地柜方法遍历添加节点 LoadSiteMap(SiteMap.RootNode, node); TreeView2.Nodes.Add(node); //======================================第三种,通过编程绑定SiteMapDataSource控件添加TreeView节点===================================== // 设计界面上增加了一个TreeView3,并新增一个SiteMapDataSource1,然后将二者通过数据源选项绑定 } protected void LoadSiteMap(SiteMapNode node, TreeNode tvNode) { // 获取根节点的子节点 int count = node.ChildNodes.Count; // 这里循环遍历节点 for (int i = 0; i < count; i++) { // 获取根节点的子节点 SiteMapNode smNode = node.ChildNodes[i]; // 从子节点获取导航信息 TreeNode tempNode = new TreeNode(smNode.Title, "", "", smNode.Url, ""); tvNode.ChildNodes.Add(tempNode); if (smNode.HasChildNodes) { // 如果当前节点还有子节点,则调用递归过程进行遍历 LoadSiteMap(smNode, tempNode); } } } } }
运行结果:
TreeView具有显示层次结构数据的优势,而开发人员通常使用XML文件来保存层次结构的数据,TreeView控件通过与XmlDataSource控件的结合,使绑定XML文件变得非常简单。
XML文件代码:
TreeView4与XmlDataSource控件代码:
这样给TreeView绑定数据源看起来挺简单的,不过不能直接绑定到SqlDataSource或者ObjectDataSource控件。
如果要加在到TreeView控件中的数据量非常大,一次性加载将显著增加服务器端的负载和客户端内存的占比量,并且会造成请求的延迟。TreeView
控件提供了按需加载的特性来解决这个问题。在首次加载时,TreeView只显示顶级节点的少量数据,当用户单击TreeView中的展开节点图标时,将再次从服务器端加载所需要的的数据。
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="PopulateOnDemand.Default" %>
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace PopulateOnDemand { public partial class Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } protected void TreeView1_TreeNodePopulate(object sender, TreeNodeEventArgs e) { for (int i = 0; i < 3; i++) { TreeNode newNode = new TreeNode(); newNode.Text = "动态加载的节点" + i.ToString(); // 这里将新建的节点的PopulateOnDemand属性也设置为True,将会形成一个无限递归 newNode.PopulateOnDemand = true; // TreeNodeEventArgs中的Node属性表示当前的节点 e.Node.ChildNodes.Add(newNode); } } } }
将绑定节点的ShowCheckBoxes
属性设置为true进行节点的复选设置。距离例子在实际应用中再查询吧。
ASP.NET提供了另一个重量级的导航控件Meun。使用该控件,开发人员可以在网页上模拟Windows的菜单导航效果。ASP.NET的Menu有两种模式:
新建Menu项目并拖入Menu控件,初始化设置:
在设计模式下,手动写入静态的菜单项:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Menu.Default" %>
运行结果:
Menu两个重要属性控制菜单是静态显示还是动态显示:
属性 | 说明 |
---|---|
StaticDisplayLevels | 控制静态显示的菜单层次,该属性默认值为1,表示只显示asp:MenuItem中第一层嵌套的节点 |
MaxiumDynamicDisplayLevels | 控制动态显示的节点层次数。默认值是3,表示可以动态地弹出3个层次的菜单。如果设置值为0则不动态显示任何菜单项。 |
通常这两个属性可以搭配使用,以获得菜单的静态和动态的显示效果。
每个MenuItem
有多个属性。如下:
属性 | 说明 |
---|---|
Text | 显示在每个菜单项上的文本 |
ToolTip | 当鼠标悬停在菜单上时显示的信息 |
Value | 存储一个附加的菜单项的数据 |
NavigateUrl | 当单击菜单项时,自动跳转到的Url地址。也可以处理Menu.MenuItemClick事件执行相应的行为 |
Target | 当NavigateUrl属性设置后,Target属性用于设置目标Url打开的框架或窗体 |
Selectable | 指定菜单项是否可以被用户选择 |
ImageUrl | 在菜单项的文本左线显示的图片Url |
PopOutImageUrl | 如果包含子菜单,则在菜单项文本的右侧显示的头像 |
SeparatorUrl | 菜单项分隔项的图片Url |
Menu控件提供了Items集合的属性,这是一个MenuItemCollection集合类型的属性,可以向该属性添加菜单项来实现动态添加菜单项的效果。
我们将原来静态添加的菜单项先注释,然后再页面的Page_Load中动态添加:
窗体代码:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Menu.Default" %>
后台代码:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace Menu { public partial class Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { MenuItem mi = new MenuItem(); mi.Text = "首页"; mi.ToolTip = "显示网站的首页"; Menu1.Items.Add(mi); MenuItem companymi = new MenuItem("公司信息"); companymi.ChildItems.Add(new MenuItem("公司信息")); companymi.ChildItems.Add(new MenuItem("公司规模")); companymi.ChildItems.Add(new MenuItem("公司人员")); Menu1.Items.Add(companymi); MenuItem productmi = new MenuItem("产品信息"); productmi.ChildItems.Add(new MenuItem("硬件产品")); productmi.ChildItems.Add(new MenuItem("软件产品")); productmi.ChildItems.Add(new MenuItem("专利产品")); Menu1.Items.Add(productmi); MenuItem servicemi = new MenuItem("服务信息"); servicemi.ChildItems.Add(new MenuItem("服务事项")); servicemi.ChildItems.Add(new MenuItem("服务申请")); servicemi.ChildItems.Add(new MenuItem("服务建议")); Menu1.Items.Add(servicemi); MenuItem aboutmi = new MenuItem("关于"); Menu1.Items.Add(aboutmi); } } }
运行结果:
Menu控件作为一种导航控件,同样可以轻松绑定到SiteMapDataSource控件来实现站点导航。
新建项目MenuNavigate:
Web.site站点地图文件代码:
运行结果:
站点地图Web.sitemap中定义的站点导航代码:
这里绑定的项还要绑定一下:
XML文件代码:
窗体设计代码:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="BingdingToXml.Default" %>
运行结果:
Menu控件与TreeView控件类似,提供了大量的外观控制项。
以下是Menu控件的样式:
静态模式样式 | 动态模式样式 | 样式说明 |
---|---|---|
StaticMenuStyle | DynamicMenuStyle | 设置Menu控件的整个外观样式 |
StaticMenuItemStyle | DynamicMenuItemStyle | 设置单个菜单项的样式 |
StaticSelectedStyle | DynamicSelectedStyle | 设置所选择的菜单项的样式 |
StaticHoverStyle | DynamicHoverStyle | 设置当鼠标悬停在菜单项上时的样式 |
ASP.NET中的Menu控件是一个强大的导航控件,允许开发人员创建复杂的菜单结构。通过使用模板(Templates),你可以自定义Menu控件的外观和行为,以满足特定的需求。以下是如何在ASP.NET中为Menu控件使用模板的详细介绍。
ASP.NET Menu控件支持以下几种模板:
StaticItemTemplate:用于静态菜单项的模板。
DynamicItemTemplate:用于动态菜单项的模板。
StaticMenuItemTemplate:用于静态菜单项的容器模板。
DynamicMenuItemTemplate:用于动态菜单项的容器模板。
以下是一个示例,展示如何为Menu控件使用模板:
2.1. ASPX页面
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="MenuTemplate.aspx.cs" Inherits="MenuTemplate" %> Menu Template Example
2.2. 代码隐藏文件(C#)
using System; using System.Web.UI.WebControls; public partial class MenuTemplate : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { BindMenu(); } } private void BindMenu() { MenuItem home = new MenuItem("Home", "Home"); MenuItem about = new MenuItem("About", "About"); MenuItem services = new MenuItem("Services", "Services"); MenuItem contact = new MenuItem("Contact", "Contact"); Menu1.Items.Add(home); Menu1.Items.Add(about); Menu1.Items.Add(services); Menu1.Items.Add(contact); MenuItem webDesign = new MenuItem("Web Design", "WebDesign"); MenuItem seo = new MenuItem("SEO", "SEO"); services.ChildItems.Add(webDesign); services.ChildItems.Add(seo); } }