asp.net控件開發基礎(13) --------服務器控件客戶端功能

  上一篇討論瞭如何爲子控件添加集合樣式,這次我們討論如何爲服務器控件添加客戶端功能 .

1.減輕服務器壓力,增加用戶體驗

         服務器功能是強大的,客戶端腳本一點也不弱,現在的ajax技術和Atlas技術就是最好的證明,我們總是期待UI有一個好的效果,flash動畫給我們帶來了很酷的效果,我們至少也可以爲我們的服務器控件添加客戶端腳本,一方面減少了服務器端的回傳,一方面又能爲控件提供非常酷的效果.我想我們都很喜歡ATLAS裏面很多很酷的控件吧,而且無刷新,服務器控件與客戶端腳本交互使用,那會服務器控件變的更加完美.

經過上面的廢話,下面我們進入正題

2.簡單爲服務器控件添加客戶端腳本

我們已經瞭解到服務器控件呈現後的代碼仍然爲HTML,只要你熟悉此服務器控件呈現後標籤和此標籤的元素,你就可以直接在服務器控件中添加
屬性,事件,樣式等等

簡單的添加方法如下:

(1)直接在控件添加屬性,如爲Button控件添加簡單的客戶端事件

<asp:Button ID="Button2" runat="server" Text="Button" onmouseover="this.value='鼠標經過'" onmouseout="this.value='鼠標離開'"  />

(2)使用AttributeCollection在後臺添加添加簡單的客戶端事件,很典型的使用如我們在刪除數據的時候總要彈出一個窗口提醒用戶是否刪除.

Button2.Attributes.Add("onmouseover""this.value='鼠標經過'");
        Button2.Attributes.Add(
"onmouseout""this.value='鼠標離開'");

3.複雜客戶端功能處理

先不論服務器端的功能,當客戶端腳本複雜以後,我們會寫在一個js文件裏,可以複用,簡單的腳本邏輯可以<script>標籤內.我們需要封裝.

Page類爲我們提供了幾個方法用於實現以下內容,但需要注意的是,asp.net2.0新加了一個類ClientScriptManager,專門用於管理客戶端腳本的方法,使用方法爲

ClientScriptManager = Page.ClientScript;


(1)註冊腳本庫(js文件)                                                          RegisterClientScriptInclude 方法

(2)發出位於頁面頂部和尾部的腳本                                   RegisterStartupScript 方法 和  RegisterClientScriptBlock 方法
 
(3)確保腳本塊在頁面只出現一次                                       以Is帶頭Registered結尾的四個方法

(4)將控件事件處理程序與客戶端提交事件關聯起來       RegisterOnSubmitStatement 方法

(5)註冊一個數組用來存儲控件自身變量                           RegisterArrayDeclaration方法

(6)註冊一個隱藏域                                                               RegisterHiddenField 方法

對於以上方法的具體使用MSDN均給出了具體的示例,剛看的時候感覺方法名比較長,接觸後就會感覺簡單了,對以上方法的使用一定要了解.如果你不想看MSDN的話,那麼推薦看下面幾篇文章,相信對你會有很大幫助.還有建議大家可以看下呈現後的HTML代碼,這樣會加深理解.

從 ASP.NET 服務器控件插入客戶端腳本

使用客戶端腳本

4.瞭解預呈現PreRender事件

這裏還是要講控件的生命週期,在控件呈現Render方法之前,還有一個預呈現OnPreRender 方法.其週期是在OnLoad之後的MSDN給出了其解釋

在呈現輸出之前執行任何更新。可以保存在預呈現階段對控件狀態所做的更改,而在呈現階段所對的更改則會丟失

總結的話,總是很簡單的,要深刻理解的話,還是需要我們去試驗一下,再回來體驗上面這句話

先看一個簡單的例子,在頁面上重寫了Page_PreRender,在其事件中給label1賦值,然後再定義了button事件,你會發現button事件觸發後label的值還是保持不變.

示例一


    protected void Page_PreRender(object sender, EventArgs e)
        
    
{
        Label1.Text
="PreRender";
        
    }


    
protected void Button1_Click(object sender, EventArgs e)
    
{
        Label1.Text 
= "Click";
    }


再理解上面這句話,可能我們想爲什麼不在呈現的時候Render方法中實現呢?如果這麼做的話,那你就要屬性定死了.

我們還需要說明一點,不同事件負責不同的事情,Render方法只負責呈現,不要把別的事情交給他做.
你可以在Render方法爲控件添加需要呈現的屬性,但其他事情則需要在呈現之前完成.整個控件的週期是有階段,不同階段完成不同事情.
我們這次討論的是爲服務器控件添加客戶端腳本,那麼我們就要在控件適當的時機調用ClientScriptManager類的方法.而這個適當的時機就是OnPreRender 方法了.


5.在自定義控件中添加客戶端腳本

(1)簡單的實現:
你可以重些OnPreRender方法,然後用AttributeCollection的Add方法,添加簡單客戶端腳本

      protected override void OnPreRender(EventArgs e)
      
{
         
base.OnPreRender(e);
         Attributes.Add(
"onclick","alert('" + ClickText + "');");
      }

(2)複雜的實現: 這裏我們用的例子還是簡單點吧,效果還是按鈕確認之前有一個彈出窗口,重要的是大家要了解ClientScriptManager類中幾個方法的使用,以下的代碼使用的是 asp.net服務器控件開發技術與實例的實例2 ,我偷懶,直接就用Page裏的幾個方法的.

以下列出代碼

示例二


/// <summary>
    
/// NormalButton 顯示爲一個普通樣式按鈕。
    
/// 當用戶點擊按鈕之後,跳出一個確認對話框來確定其動作。
    
/// 通常多用於確認用戶是否確實要進行刪除/修改等類似的操作。
    
/// </summary>

    [ToolboxData("<{0}:NormalButton runat=server></{0}:NormalButton>")]
    
public class NormalButton : Button
    
{
        
private string _scriptPath = "ControlClientScript/";
        
//構造函數
        public NormalButton():base()
        
{
            Message 
= "您確實要這樣做嗎?";
        }

        
        
#region 定義屬性

        [Bindable(
true), 
        Category(
"Appearance"), 
        DefaultValue(
"您確實要這樣做嗎?"),
        Description(
"自定義提示信息")] 
        
public string Message 
        
{
            
get
            
{
                
return (string)ViewState["Message"];
            }


            
set
            
{
                ViewState[
"Message"= value;
            }

        }

        
        [Category(
"Other"), 
        DefaultValue(
"ControlClientScript/"),
        Description(
"腳本路徑")]
        
public String ScriptPath 
        
{
            
get 
            
{
                
return _scriptPath;
            }

            
set
            
{
                _scriptPath 
= value;
            }

        }


        
#endregion


        
//重寫AddAttributesToRender方法
        protected override void AddAttributesToRender(HtmlTextWriter output)
        
{
            Attributes.Add(
"confirmationmessage",Message);
            
base.AddAttributesToRender(output);

        }


        
//重寫OnPreRender方法
        protected override void OnPreRender( EventArgs e ) 
        
{
            Page.RegisterClientScriptBlock( 
"WebUIConfirmation""<script language='javascript' src='" + ScriptPath + "WebUIConfirmation.js" + "'></script>" );
            Page.RegisterArrayDeclaration(
"Page_Confirmations""'" + ClientID + "'" );
            Page.RegisterStartupScript( 
"WebUIConfirmation Startup""<script language='javascript' src='" + ScriptPath + "WebUIConfirmationStartup.js" + "'></script>" );
            
base.OnPreRender(e);
        }

    }

 
主要看OnPreRender方法,只要你對其幾個方法熟悉後,那剩下就是你對javaScript的掌握程度了.掌握上面幾個方法可以說很容易,對javaScript的掌握那需要平時的積累了,所以要開發一個好的控件,並不容易呀.

下面再列出js文件,我對其梢有改動

WebUIConfirmationStartup.js

ConfirmationOnLoad();

WebUIConfirmation.js


//String去空格
String.prototype.Trim = function()

return this.replace(/(^/s*)|(/s*$)/g, "");
}


//初始化獲取控件ID
function ConfirmationOnLoad() {    
    
if (typeof(Page_Confirmations) == "undefined"return;
    
var i, confirmButton;
    
for (i = 0; i < Page_Confirmations.length; i++{
        confirmButton 
= Page_Confirmations[i];
        
if (typeof(confirmButton) == "string"{
            confirmButton 
= document.getElementById( confirmButton );
        }
        
        
if (typeof(confirmButton.confirmationmessage ) != "undefined" ) {
            
if ( confirmButton.attributes["confirmationmessage"].value.Trim() != "" ) {
                confirmButton.confirmationmessage 
= confirmButton.attributes["confirmationmessage"].value;
            }
 else {
                confirmButton.confirmationmessage 
= "您確實要這樣做嗎?";
            }

        }

        ConfirmationHookupControl(confirmButton);
        
    }

}


//添加onclick事件
function ConfirmationHookupControl( confirmButton ) {
    
var ev = confirmButton.onclick;
    
if (typeof(ev) == "function" ) {            
        ev 
= ev.toString();
        ev 
= ev.substring(ev.indexOf("{"+ 1, ev.lastIndexOf("}"));
    }

    
else {
        ev 
= "";
    }

    
var func = new Function("if ( !ConfirmationOnClick( this ) ){return false;} " + ev);
    confirmButton.onclick 
= func;
}


//彈出確認窗口
function ConfirmationOnClick( confirmButton ) {
    
return window.confirm( confirmButton.confirmationmessage );
}



OK,上面的服務器控件代碼還是挺簡單的,你看的懂JS的話,那這個效果就沒問題了.其實說真的,難點在於JavaScript腳本,呵呵.

下面再說一個例子吧,也是asp.net服務器控件開發技術與實例的例子,是一個可伸縮面板控件,其是一個集合屬性和客戶端腳本一起實現的效果

但此控件卻並在呈現頁面上用到js腳本,也沒重寫OnPreRender方法,而是定義了一個HTC,其關鍵實現是服務器控件的集合屬性的實現,還有就是客戶端腳本的實現,具體代碼可以在後面下載.

其他:
1.客戶端腳本在服務器控件中的最頻繁的使用則是驗證控件的使用了,你也可以自定義驗證控件,但我感覺用處不是很大,如果需要你可以瞭解下System.Web.UI.IValidator 接口和System.Web.UI.WebControls.BaseValidator類

2.另外還有客戶端回調,你可以瞭解下ICallbackEventHandler接口,具體還是看相關文章或者MSDN吧.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章