最近一个项目有个页面导航的需求,就是在总页面里支持子页面的跳转,同时记录跳转历史,实现向后向前跳转的功能,类似浏览器的向前向后导航按钮。子页面我简单的用iframe实现了,跳转历史跟踪参考了一下Asp.Net本质论的一个例子,这里把整个代码分享一下。
最核心的是导航组件:
public class PathNavigator : Control
{
private Stack<string> _prevs = new Stack<string>();
private Stack<string> _nexts = new Stack<string>();
private string _current = null;
/// <summary>
/// 当前页面
/// </summary>
public string CurrentPage
{
get
{
return _current;
}
set
{
_current = value;
}
}
/// <summary>
/// 主动跳转到页面
/// </summary>
/// <param name="path">页面路径</param>
public void EnterPage(string path)
{
if (_current != null)
_prevs.Push(_current);
_nexts.Clear();
_current = path;
}
/// <summary>
/// 跳转到前一个页面
/// </summary>
public void Prev()
{
if (_prevs.Count > 0)
{
_nexts.Push(_current);
_current = _prevs.Pop();
OnJump();
}
}
/// <summary>
/// 跳转到后一个页面
/// </summary>
public void Next()
{
if (_nexts.Count > 0)
{
_prevs.Push(_current);
_current = _nexts.Pop();
OnJump();
}
}
/// <summary>
/// 加载跳转历史
/// </summary>
/// <param name="savedState"></param>
protected override void LoadViewState(object savedState)
{
var triplet = savedState as Triplet;
if (triplet != null)
{
_nexts.Clear();
_prevs.Clear();
_prevs = triplet.First as Stack<string>;
_nexts = triplet.Second as Stack<string>;
_current = triplet.Third as string;
}
}
/// <summary>
/// 保存跳转历史数据
/// </summary>
/// <returns></returns>
protected override object SaveViewState()
{
Triplet triplet = new Triplet();
triplet.First = _prevs;
triplet.Second = _nexts;
triplet.Third = _current;
return triplet;
}
private void OnJump()
{
if (PageJump != null)
{
PageJump(this, null);
}
}
/// <summary>
/// 向前或向后跳转时激发
/// </summary>
public event EventHandler PageJump = null;
}
主页面包含一个下拉框和两个按钮,下拉框实现跳转到某个页面,两个按钮实现向前向后。
.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="NavMainPage.aspx.cs" Inherits="WebLearn.Navigate.NavMainPage" %>
<%@ Register assembly="WebLearn" namespace="WebLearn.Navigate" tagprefix="nav" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:DropDownList ID="ddlPath" runat="server" AutoPostBack="true"
OnSelectedIndexChanged="ddlPath_SelectedIndexChanged" >
<asp:ListItem Value="NavPage1.aspx" Selected="True">页面1</asp:ListItem>
<asp:ListItem Value="NavPage2.aspx">页面2</asp:ListItem>
<asp:ListItem Value="NavPage3.aspx">页面3</asp:ListItem>
</asp:DropDownList>
<asp:Button ID="Button1" Text="<-" runat="server" onclick="Button1_Click"/>
<asp:Button ID="Button2" Text="->" runat="server" onclick="Button2_Click"/>
<nav:PathNavigator ID="navigator" runat="server">
</nav:PathNavigator>
<br />
<iframe style="border-style:none;" src="<%=navigator.CurrentPage%>" />
</form>
</body>
</html>
.cs
public partial class NavMainPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
navigator.CurrentPage = ddlPath.SelectedValue;
}
navigator.PageJump += new EventHandler(navigator_PageJump);
}
void navigator_PageJump(object sender, EventArgs e)
{
ddlPath.SelectedValue = navigator.CurrentPage;
}
protected void Button1_Click(object sender, EventArgs e)
{
navigator.Prev();
}
protected void Button2_Click(object sender, EventArgs e)
{
navigator.Next();
}
public void BindPages(Dictionary<string, string> pagePairs)
{
ddlPath.DataSource = pagePairs;
ddlPath.DataTextField = "Value";
ddlPath.DataValueField = "Key";
ddlPath.DataBind();
}
protected void ddlPath_SelectedIndexChanged(object sender, EventArgs e)
{
navigator.EnterPage(ddlPath.SelectedValue);
}
}
子页面比较简单,从一个Master模板继承,每个页面包含了一段不同的文本加以区别。
Master
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Nav.master.cs" Inherits="WebLearn.Navigate.Nav" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ContentPlaceHolder ID="MainContent" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
Page1
<%@ Page Language="C#" AutoEventWireup="true" MasterPageFile="~/Navigate/Nav.Master"
CodeBehind="NavPage1.aspx.cs" Inherits="WebLearn.Navigate.NavPage1"%>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
这里是第一个页面
</asp:Content>
Page2
<%@ Page Language="C#" AutoEventWireup="true" MasterPageFile="~/Navigate/Nav.Master"
CodeBehind="NavPage2.aspx.cs" Inherits="WebLearn.Navigate.NavPage2" %>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
这里是第二个页面
</asp:Content>
Page3
<%@ Page Language="C#" AutoEventWireup="true" MasterPageFile="~/Navigate/Nav.Master"
CodeBehind="NavPage3.aspx.cs" Inherits="WebLearn.Navigate.NavPage3" %>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
这里是第三个页面
</asp:Content>