[轉]"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腳本的頁面,就不要考慮了。

    羅嗦了半天,真正的主角還沒有出場,真是失敗red_smile.gif。下面就就來看看我的“SmartNavigation“的超級瘦身減肥苗條版:
    其實也太簡單了,就是記錄Post時的ScrollTop,Response後在set這個ScrollTop到提交時的位置,不過我做了一個控件,拖到頁面上就讓該頁面具有Navigate的功能了。代碼如下:
None.gifusing System;
None.gif
using System.Collections;
None.gif
using System.ComponentModel;
None.gif
using System.Drawing;
None.gif
using System.Text;
None.gif
using System.Web;
None.gif
using System.Web.UI;
None.gif
using System.Web.UI.Design;
None.gif
using System.Web.UI.WebControls;
None.gif
using System.Web.UI.HtmlControls;
None.gif
None.gif
namespace Birdshome.Web.UI.WebControls
ExpandedBlockStart.gif
{
ExpandedSubBlockStart.gif    
/// <summary>
InBlock.gif    
/// Summary description for Class1.
ExpandedSubBlockEnd.gif    
/// </summary>

InBlock.gif    [Designer(typeof(Birdshome.Web.UI.Design.ClientNavigationDesigner))]
InBlock.gif    [ToolboxData(
"<{0}:ClientNavigation runat="server"></{0}:ClientNavigation>")]
InBlock.gif    
public class ClientNavigation : WebControl, INamingContainer, IPostBackDataHandler
ExpandedSubBlockStart.gif    
{
ExpandedSubBlockStart.gif        
public ClientNavigation() : base() {}
InBlock.gif
InBlock.gif        
public int Position
ExpandedSubBlockStart.gif        
{
InBlock.gif            
get
ExpandedSubBlockStart.gif            
{
InBlock.gif                
object obj = ViewState["Position"];
InBlock.gif                
return obj == null ? 0 : (int)obj;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gif            
{
InBlock.gif                ViewState[
"Position"= value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
protected override void Render(HtmlTextWriter writer)
ExpandedSubBlockStart.gif        
{
InBlock.gif            
this.RegisterClientScript();
InBlock.gif            writer.AddAttribute(HtmlTextWriterAttribute.Type, 
"hidden");
InBlock.gif            writer.AddAttribute(HtmlTextWriterAttribute.Id, 
this.ClientID);
InBlock.gif            writer.AddAttribute(HtmlTextWriterAttribute.Name, 
this.ClientID);
InBlock.gif            writer.AddAttribute(HtmlTextWriterAttribute.Value, 
this.Position.ToString());
InBlock.gif            writer.RenderBeginTag(HtmlTextWriterTag.Input);
InBlock.gif            writer.RenderEndTag();
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private void RegisterClientScript()
ExpandedSubBlockStart.gif        
{
InBlock.gif            
const string REGISTER_KEY = "__ClientNavigate586787__";
InBlock.gif            
string strScript = @"
InBlock.gif
                <script language=""javascript"">
InBlock.gif                window.onload 
= function()
ExpandedSubBlockStart.gif                
{{
ExpandedSubBlockStart.gif                    var scrollPsn 
= {0};
InBlock.gif                    var scrollCount 
= 0
InBlock.gif                    
do
ExpandedSubBlockStart.gif                    
{{
InBlock.gif                        scrollCount 
++;
InBlock.gif                        window.scrollTo(
0, scrollPsn);
ExpandedSubBlockEnd.gif                    }
}

InBlock.gif                    
while(document.body.scrollTop < scrollPsn && scrollCount < 10 );
ExpandedSubBlockEnd.gif                }
}

InBlock.gif                document.body.onscroll 
= function()
ExpandedSubBlockStart.gif                
{{
ExpandedSubBlockStart.gif                    document.all.
{1}.value = document.body.scrollTop;
ExpandedSubBlockEnd.gif                }
}

InBlock.gif                
</script>";
InBlock.gif
            if ( !this.Page.IsStartupScriptRegistered(REGISTER_KEY) )
ExpandedSubBlockStart.gif            
{
InBlock.gif                strScript 
= String.Format(strScript, this.Position, this.ClientID);
InBlock.gif                
this.Page.RegisterStartupScript(REGISTER_KEY, strScript);
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
ContractedSubBlock.gif        
IPostBackDataHandler Members
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}
    這個ClientNavigation有個問題,就是可以拖多個到一個頁面,雖然不影響使用,但不知道有沒有好辦法能讓控件只能在一個Page上最多放一個呢?
發佈了47 篇原創文章 · 獲贊 0 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章