前几天做web项目的时候, 使用了ajax方面的updatepanel控件.使用后效果的确很酷.然而让人很头大的是关于History的操作问题.用户没有办法使用back 和 forward按钮行使相应的操作.
解决方案一:
在web页面使用自己的back 和 forward link. 同时, 使用自己的hashtable 维护一组历史记录. 需要back的页面需要通过程序在该hash表中注册.
1. 定义接口IBreadCrumbProvider. 该接口定义了常规注册方法.
Code
public interface IBreadCrumbProvider
{
void Activate(string id, string title);
void Activate( string id, string title, int seedValue);
void Activate(string id, string title, string url, int seedValue);
void Activate(string id, string title, string url);
void Activate(string id, string title, string url, int seedValue, IComparer<BreadCrumb> iComparer);
void Activate(string id, string title, string url, IComparer<BreadCrumb> iComparer);
void Modify(string id, int delta);
void Clear();
}
在该定义中,id 是将要注册的page的guid, 以便让其唯一. title为page的title,seedvalue标识将要过期时间. url为url路径.而comparer则用来注册该page时,是否要覆盖过去的记录.
2. 定义BreadCrumb和BreadCrumbs.
显然, BreadCrumb用来表示单一的对象, 而后者是该单一对象的list. 对单一的对象, 应该暴露接口中需要的属性. 而对list对象, 应该暴露注册和删除的方法.
Code
public class BreadCrumbs
{
Stack<BreadCrumb> m_breadCrumbs = new Stack<BreadCrumb>();
public BreadCrumbs()
{
}
public static BreadCrumbs Load()
{
BreadCrumbs bcs = System.Web.HttpContext.Current.Session[/*MSG0*/"PSE_BREADCRUMBS"] as BreadCrumbs;
if (null == bcs)
{
bcs = new BreadCrumbs();
System.Web.HttpContext.Current.Session[/*MSG0*/"PSE_BREADCRUMBS"] = bcs;
}
return bcs;
}
public static void Persist(BreadCrumbs breadcrumbs)
{
// do nothing since we are storing in Session variable but in the future
// we may do other persistence would require a persist method call.
}
public BreadCrumb[] ToArray()
{
return m_breadCrumbs.ToArray();
}
public void Clear()
{
m_breadCrumbs.Clear();
}
public bool IsEmpty()
{
return 0 == m_breadCrumbs.Count;
}
public void Add(BreadCrumb bc)
{
m_breadCrumbs.Push(bc);
}
public void Push(BreadCrumb bc)
{
this.m_breadCrumbs.Push(bc);
}
public BreadCrumb Peek()
{
if (0 != this.m_breadCrumbs.Count)
return m_breadCrumbs.Peek() as BreadCrumb;
return null;
}
public BreadCrumb Pop()
{
if (0 != m_breadCrumbs.Count)
return m_breadCrumbs.Pop() as BreadCrumb;
return null;
}
public BreadCrumb Pop(Guid breadCrumbId)
{
BreadCrumb[] bcs = m_breadCrumbs.ToArray();
m_breadCrumbs.Clear();
for (int i = bcs.Length - 1; i >= 0; i--)
{
BreadCrumb bc = bcs[i];
if (bc._id != breadCrumbId)
m_breadCrumbs.Push(bc);
else
return bc;
}
return null;
}
public BreadCrumb Get(string id)
{
foreach (BreadCrumb bc in m_breadCrumbs)
if (bc.Id == id)
return bc;
return null;
}
public BreadCrumb Acquire(int level, string id, string title, int seedValue)
{
return Acquire(level, id, title, "", seedValue, null);
}
/// <summary>
/// Gets existing breadcrumb or new breadcrumb and modifies the breadcrumb statck as appropriate.
/// </summary>
/// <param name="level"></param>
/// <param name="id"></param>
/// <param name="title"></param>
/// <param name="url"></param>
/// <param name="seedValue"></param>
/// <param name="iComparer"></param>
/// <returns></returns>
public BreadCrumb Acquire(int level, string id, string title, string url, int seedValue, IComparer<BreadCrumb> iComparer)
{
if (null == iComparer)
iComparer = new DefaultBreadCrumbComparer();
//// create a temporary breadcrumb for comparison;
//// create a new crumb if necessary
BreadCrumb tmpbc = null;
tmpbc = new BreadCrumb();
tmpbc.Level = level;
tmpbc.Id = id;
tmpbc.Title = title;
tmpbc.HistoryToPrevious = seedValue;
tmpbc.Url = url;
if (1 == tmpbc.Level)
{
// clear and reset.
Clear();
Push(tmpbc);
return tmpbc;
}
BreadCrumb bc = Peek();
while(null != bc)
{
int result = iComparer.Compare(bc, tmpbc);
if (result < 0)
{
Pop();
bc = Peek();
}
else if (0 == result)
{
return bc;
}
else
{
Push(tmpbc);
return tmpbc;
}
}
Push(tmpbc);
return tmpbc;
}
public BreadCrumb GetPrevious(BreadCrumb bc)
{
BreadCrumb[] list = m_breadCrumbs.ToArray();
if (list.Length < 2)
return null;
else
return list[1];
}
}
3. 让需要注册的page实现接口. 然后调用BreadCrumbs中对应的方法.
该方法主要是使用BreadCrumbs的Laod() 和Acquir()方法
BreadCrumbs m_breadCrumbs = BreadCrumbs.Load();
解决方案二:
使用IE自己的history对象来处理. 方法在下结介绍.