當前位置:開發者網絡 >> 技術教程 >> .NET教程 >> Asp.Net開發 >> 內容
精彩推薦
分類最新教程
分類熱點教程
    
實現一個Asp.net自定義Back控件
作者:未知
日期:2005-04-14
人氣:
投稿:(轉貼)
來源:未知
字體:
收藏:加入瀏覽器收藏
以下正文:
本文講述了如何給Web頁面添加一個服務器端控件,從而將用戶的瀏覽器重定向到該控件所指向的頁面(referring page)。 
by Juval Lowy
Q:實現一個ASP.NET Back控件
我想在ASP.NET頁面中添加一個鏈接,通過它,我可以返回到它所指向的頁面。不知怎樣用一個服務器端控件來實現它呢?我想通過該控件返回到已訪問過的頁面,而並不想用瀏覽歷史記錄的方法。
A:
你可以用兩種方法在一個Web頁面上實現一個「Back」鏈接。第一種方法是用客戶端腳本讀取前面已訪問過的頁面的記錄,並將它重定向到前一個頁面:
<a href= "javascript:history.back()">Back</a>

不過這種方法有幾個缺點。應用程序不能控制用戶被重定向到了哪裡。通常情況下,你總是想讓用戶留在應用程序內,而不想讓他們跑到其它頁面。只有當瀏覽器支持客戶端腳本時,這種方法才可行。其最大的缺點就是它與ASP.NET編程模式不一致。ASP.NET的一個最大的好處就是它不同於傳統的ASP,它不需要你依賴於客戶端腳本。你只需要知道如何使用你用托管代碼寫的服務器端控件就行了,ASP.NET會為你完成其它的工作。在使用客戶端腳本時,Back鏈接與應用程序的其它部分是沒有關係的,它是在服務器上運行的,並運用了服務器端的控件。這會使你很難控制是否激活Back鏈接,而且你也很難控制重定向,因為它們都是以服務器端事件處理程序為基礎的。
第二種方法是用一個ASP.NET自定義的用戶控件。本文所附帶的源文件在WebControlsEx類庫程序集中包含一個BackLink ASP.NET用戶控件。如果要用該控件,你需要右擊Web Forms工具箱,從彈出的上下文菜單中選擇Add/Remove Items。點擊.NET Frameworks Components Tab鍵並按Browse按鈕。選擇WebControlsEx程序集,點Open。這樣就在toolbox上添加了BackLink用戶控件。你只需要將它拖放到你的form中,就可以添加一個鏈接式的控件了,其text屬性是「Back」。在設計時,該控件具有與標準的鏈接按鈕一樣的屬性,如鏈接樣式(見圖1)。當用戶在運行時點擊該按鈕時,它會將瀏覽器引導到前一個頁面(如果有的話)。
實現BackLink用戶控件並不像我們所看到的那麼簡單。要構建一個Web用戶控件,你必須用DLL類庫。你可以通過兩種方法來提供一個用戶控件:繼承一個叫做WebControl的類並對它進行自定義,或繼承一個現有的控件並進行自定義。對於BackLink控件來說,目前一個比較好的方法就是繼承一個LinkButton,因為LinkButton控件提供了大部分很難實現的功能。
你可以從LinkButton繼承一個叫做BackLink的類,在它的構造器中將Text屬性設置為Back,並提供一些有意義的缺省值:
public class BackLink : LinkButton
{
   public BackLink()
   {
      Text = "Back";
   }


實際上,繼承一個LinkButton在HTML中可以體現出來。通過繼承BackLink,該控件在設計器中可以體現LinkButton所有的屬性——如缺省的屬性、字體設置屬性和事件。
LinkButton有一個叫做OnClick()的受保護的虛擬方法,當返回頁面時,.NET會調用該方法,讓鏈接按鈕觸發點擊事件。LinkButton必須覆蓋OnClick()並將用戶重定向到控件所指向的頁面。
重要的問題是在BackLink控件範圍內,如何在服務器端得到當前頁面所指向的頁面。幸運的是,ASP.NET具有這樣的功能:HttpRequest對像提供了一個Url類型的公開的屬性,稱為UrlReferrer,它表示的是所指向頁面的URL。LinkButton用戶控件可以得到對頁面的引用,這是通過Control類的Page屬性實現的。Control是WebControl的基類,WebControl是LinkButton的基類。該控件也可以用Page屬性來讀取其HttpResponse對像(Response屬性),從而將用戶重定向到所指向的頁面。
然而,如果你用下面的代碼來實現BackLink控件,那麼該鏈接會不起作用:public class BackLink : LinkButton
{
   public BackLink()
   {
      Text = "Back";
   }
   protected override void 
      OnClick(EventArgs e)
   {
      Uri backURL = 
         Page.Request.UrlReferrer;
      Page.Response.Redirect(
         backURL.AbsoluteUri);
   }
}

原因在於ASP.NET跟蹤所指向頁面的方式。例如,我們以Home.aspx頁面為例,它會將用戶引導到SubForm.aspx頁面。如果SubForm.aspx頁面有一個BackLink控件,用戶點擊該鏈接後,就會觸發返回頁面到服務器的事件。服務器上UrlReferrer屬性的值是「SubForm.aspx」(而不是「Home.aspx」),因為當返回頁面時,SubForm.aspx指向的是它自己。解決方法就是在加載控件時,在session變量中緩存所指向的頁面,並在OnClick()中重定向到所指向的頁面。
現在,你還需要解決幾個問題:ASP.NET並不是總能提供具有導向信息的頁面的,在這種情況下,ASP.NET將UrlReferrer的值設置為空。你也需要提供一個「智能的」Back鏈接,它可以重定向到邏輯上的前一個頁面。換句話說,如果一個包含BackLink的頁面自己重載(在處理了一些控件的點擊事件後),Back鏈接應該可以很「聰明」地檢測到這一點,並重定向到「真實」的前一個頁面,而不是它本身。注意,如果你用客戶端代碼,這是不可能實現的,因為在再次載入時,Back記錄變量會呈現同樣的頁面。
BackLink覆蓋了其基類的OnLoad()方法(見列表1)。當加載包含BackLink控件的頁面時,調用OnLoad()。OnLoad()首先查看是否有所指向的頁面信息。如果UrlReferrer是空的,那麼OnLoad()就會讓Back鏈接不起作用。如果有導向信息,你需要驗證所指向的頁面不是當前頁面。你可以通過比較所指向頁面的URL和請求頁面的URL來實現這一點:
if(backURL.AbsolutePath != Page.Request.Url.AbsolutePath)
如果兩個URL不一樣,BackLink就把所指向頁面的URL保存在一個session變量中:
Page.Session["Referring URL"] = backURL;
然後它會激活該控件。如果地址是一樣的,BackLink在激活控件前,需要驗證所指向頁面的URL是否已經緩存過了。在OnClick()中,你必須讀取session變量,如果session變量存在,就將用戶重定向到控件指向的頁面。
你也可以在可視化設計頁面上設計用戶控件。當你將控件拖放到Web form時,ToolboxData屬性會告訴VS.NET在ASPX文件中插入什麼。ToolboxBitmap包含對控件圖標的一個引用(以嵌入資源的形式)。如圖1所示,一旦你添加了控件,圖標就會顯示在toolbox中。

源代碼:
[ToolboxData("<{0}:BackLink runat=server></{0}:BackLink>")]
[ToolboxBitmap(typeof(BackLink),"BackLink.bmp")]
public class BackLink : LinkButton
{
    public BackLink()
    {
        Text = "Back";
        ToolTip = 
            "Click to go to the previous page";
    }

    protected override void OnClick(EventArgs e)
    {
        Uri backURL = (Uri)Page.Session[
            "Referring URL"];
        Page.Session["Referring URL"] = null;
        if(backURL != null)
        {
            Page.Response.Redirect(
                backURL.AbsoluteUri);
        }
    }

    protected override void OnLoad(EventArgs e)
    {
        Uri backURL = Page.Request.UrlReferrer;
        if(backURL == null) //No referrer 
            information 
        {
            Enabled = false;
            return;
        }
        if(backURL.AbsolutePath != 
            Page.Request.Url.AbsolutePath)
        {
            Page.Session["Referring URL"] =  
                backURL;
            Enabled = true;
            return;
        }
        else
        {
            object obj = Page.Session[
                "Referring URL"];
            if(obj != null)
            {
                Enabled = true;
            }
        }
        base.OnLoad(e);
    }
}
相關文章: