天天看點

"SmartNavigation"超級瘦身減肥苗條版ClientNavigation

在我的上兩片文章中我介紹了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

    }

}

    這個ClientNavigation有個問題,就是可以拖多個到一個頁面,雖然不影響使用,但不知道有沒有好辦法能讓控件隻能在一個Page上最多放一個呢?

本文轉自部落格園鳥食軒的部落格,原文連結:http://www.cnblogs.com/birdshome/,如需轉載請自行聯系原部落客。

繼續閱讀