在我的上两片文章中我介绍了Page类的SmartNavigation属性的实现(.NET Framework
1.1/
2.0中 SmartNavigation的实现),M$虽然实现的非常的巧妙,但是这样的“偷梁换柱”同时也带来了一些负面的影响。他们主要表现在这几个方面:
1、页面不能再使用浏览器提供的forward和backward,因为这两个动作作用在window.document对象上,而我们实际提交的页面是这个document里的IFrame,它是不能被f&b的。这个问题挺郁闷的,因为用户不能backward,在提交的时候会丢失很多第一次未能提交成功的表单信息;
2、给调试程序代来麻烦,我们看不到当前页面真正的HTML源码,因为服务器response的信息也还是IFrame中,我们只能看到doucment中陈旧的信息;
3、对于原始页面使用了动态生成html对象的情况,SmartNavigation是肯定出问题的。就是页面更新后,由于doucment实际没有更新,IFrame里也没有处理到动态生成的Html对象。
4、兼容性,目前的SmartNavigation都没有考虑兼容性问题,像Opera, Konqueror等浏览器,不能正确地Navigate;
5、不能获取Request.UrlReferrer引用,UrlReferrer总是空;
6、对于提交表单后,使用rander一段alert(...)来产生对用户提示的页面,在使用SmartNavigation的页面时,提交后不能显示预期的alert窗口;
7、对一些特殊符号的提交产生bug,比如在使用SmartNavigation的页面中,如果向TextBox中写入一个“`“(按一下Esc下面那个键)开头的值。Submit后,TextBox会消失掉,在Submit一下,TextBox出现,但里面的值已经没有了;
8、页面中写在<head>内的CSS styesheet,在第一次Submit后就会丢失,这个从1.1的SmartNavigation源代码里可以看到,他在处理<head>时,只处理了<title>和<mate>;
9、DefaultRedirect属性不能正确执行,这个可以查看M$的
KB813831。
总的说来,SmartNavigation的出现还是不错的,不过由于它真正的复杂,也同时导致了不少的问题。所以使用SmartNavigation功能一定要慎重,同时对于太复杂并内嵌大量JScript脚本的页面,就不要考虑了。
罗嗦了半天,真正的主角还没有出场,真是失败
。下面就就来看看我的“SmartNavigation“的超级瘦身减肥苗条版:
其实也太简单了,就是记录Post时的ScrollTop,Response后在set这个ScrollTop到提交时的位置,不过我做了一个控件,拖到页面上就让该页面具有Navigate的功能了。代码如下:
using
System;
using
System.Collections;
using
System.ComponentModel;
using
System.Drawing;
using
System.Text;
using
System.Web;
using
System.Web.UI;
using
System.Web.UI.Design;
using
System.Web.UI.WebControls;
using
System.Web.UI.HtmlControls;
namespace
Birdshome.Web.UI.WebControls
{
/**//// <summary>
/// Summary description for Class1.
/// </summary>
[Designer(typeof(Birdshome.Web.UI.Design.ClientNavigationDesigner))]
[ToolboxData("<{0}:ClientNavigation runat="server"></{0}:ClientNavigation>")]
public class ClientNavigation : WebControl, INamingContainer, IPostBackDataHandler
{
public ClientNavigation() : base() {}
public int Position
{
get
{
object obj = ViewState["Position"];
return obj == null ? 0 : (int)obj;
}
set
{
ViewState["Position"] = value;
}
}
protected override void Render(HtmlTextWriter writer)
{
this.RegisterClientScript();
writer.AddAttribute(HtmlTextWriterAttribute.Type, "hidden");
writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);
writer.AddAttribute(HtmlTextWriterAttribute.Name, this.ClientID);
writer.AddAttribute(HtmlTextWriterAttribute.Value, this.Position.ToString());
writer.RenderBeginTag(HtmlTextWriterTag.Input);
writer.RenderEndTag();
}
private void RegisterClientScript()
{
const string REGISTER_KEY = "__ClientNavigate586787__";
string strScript = @"
<script language=""javascript"">
window.onload = function()
{{
var scrollPsn = {0};
var scrollCount = 0;
do
{{
scrollCount ++;
window.scrollTo(0, scrollPsn);
}}
while(document.body.scrollTop < scrollPsn && scrollCount < 10 );
}}
document.body.onscroll = function()
{{
document.all.{1}.value = document.body.scrollTop;
}}
</script>";
if ( !this.Page.IsStartupScriptRegistered(REGISTER_KEY) )
{
strScript = String.Format(strScript, this.Position, this.ClientID);
this.Page.RegisterStartupScript(REGISTER_KEY, strScript);
}
}
IPostBackDataHandler Members#region IPostBackDataHandler Members
public void RaisePostDataChangedEvent()
{
// TODO: Add ClientNavigation.RaisePostDataChangedEvent implementation
}
public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
{
int iPosition = int.Parse(postCollection[postDataKey]);
if ( iPosition != this.Position )
{
this.Position = iPosition;
return true;
}
return false;
}
#endregion
}
}
这个ClientNavigation有个问题,就是可以拖多个到一个页面,虽然不影响使用,但不知道有没有好办法能让控件只能在一个Page上最多放一个呢
?