在試圖為客戶開發一個在網路上啟動並執行應用程式時,我發現有關正確使用.NET Web控制項的討論非常少。下面是使用.NET Web控制項的常見問題:
1、如何使這些控制項間相互連訊?
2、如何使這些控制項保持狀態?
3、如何將多個控制項有效地聯結在一個網頁上?
我是一名ASP開發人員,發現轉向ASP.NET並非是件輕而易舉事。我最初的想法是通過Session對象或使用查詢語句保持狀態,但發現這二種方法都太邋遢,而且,當試圖對網頁上的所有Web控制項進行同步時就會出現問題。我在偶然間發現了一篇有關在Web控制項中建立事件的文章,但在實踐中仍然吃足了苦頭,因此,我認為提供一個有關正確地建立Web控制項並同時建立定製事件的執行個體是非常重要的。
討論將按照下面的順序進行:
1、建立一個Web控制項
2、建立控制項的定製事件和事件參數
3、在網頁上正確地使用Web控制項
在討論期間,我還會向讀者提供一些小技巧,使讀者能夠更精確和快速地開發應用程式。
我們在這裡建立的Web控制項是一個定製的下拉選擇框,它基於標準版本的SQL Server或MSDE的pubs資料庫中的stores表。在開發中我們使用了Visual Studio .NET 2003開發工具和C#程式設計語言。
在建立Pubs Web項目後,第一個任務(至少對於我是如此)是將WebForm1.aspx檔案改名為Default.aspx,並修改類,使之與名字相符。然後是在IDE環境中建立一個檔案夾結構,方便對象的尋找。
我將把控制項命名為StoreSelector.ascx。第一步是在表單上添加DropDownList控制項。
(圖2)
現在就該為該控制項“布線”了。建立一個Dataset類的對象:
#code private DataSet data; #end code |
建立向下拉式清單中填寫資料的BindData功能:
#code private void BindData() { data = new DataSet(); SqlConnection cnn = new SqlConnection("Data Source=(local);Initial Catalog=pubs;Integrated Security=SSPI"); SqlDataAdapter adapter = new SqlDataAdapter(); adapter.SelectCommand = new SqlCommand("SELECT stor_id, stor_name,stor_address, city, state, zip FROM stores", cnn); adapter.Fill(data, "stores"); storeList.DataSource = data; storeList.DataMember = "stores"; storeList.DataTextField = "stor_name"; storeList.DataBind(); Session.Add("Data", data); } #end code |
我在Session變數上增加了DataSet對象,以使資料在對話存在期間以及控制項事件觸發期間傳遞資料時都是可以訪問的。注意,要確保Page_OnLoad事件的正確:
#code private void Page_Load(object sender, System.EventArgs e) { if(!Page.IsPostBack) { BindData(); } } #end code |
現在我們將新控制項拖到Default.aspx網頁上,並運行該項目。
(圖3)
(圖4)
很簡單是吧?下面就該是技巧比較高的部分了。我們希望在Default.aspx上添加幾個標籤,反映不斷變化的商店。我們希望每個標籤顯示現在選擇的商店中的一列,在這裡我們就需要為StoreSelector控制項和事件參數類建立一個定製事件。下面我們先建立Event Argument Class(StoreSelectorCommandEventArgs.cs):
#code public class StoreSelectorCommandEventArgs { private string _stor_id; private string _stor_name; private string _stor_address; private string _city; private string _state; private string _zip; public StoreSelectorCommandEventArgs(string stor_id, string stor_name, string stor_address, string city, string state, string zip) { _stor_id = stor_id; _stor_name = stor_name; _stor_address = stor_address; _city = city; _state = state; _zip = zip; } public string stor_id{ get{ return _stor_id; } } public string stor_name{ get{ return _stor_name; } } public string stor_address{ get{ return _stor_address; } } public string city{ get{ return _city; } } public string state{ get{ return _state; } } public string zip{ get{ return _zip; } } } #end code |
該類的目的是為了處理定義事件參數的“e”變數,我們要做的僅僅是建立了其中的一個。下面是定義如何處理事件的代理類(StoreSelectorCommandEventHandler.cs):
#code public delegate void StoreSelectorCommandEventHandler(object sender, StoreSelectorCommandEventArgs e); #end code |
下面是產生的檔案:
(圖5)
現在我們來調整StoreSelector控制項,觸發事件。
下面的代碼需要添加到StoreSelector控制項中,才可能執行我們建立的事件:
#code public event StoreSelectorCommandEventHandler StoreSelectorChanged; protected virtual void OnStoreSelectorChanged(StoreSelectorCommandEventArgs e) { if(StoreSelectorChanged != null) StoreSelectorChanged(this, e); } #end code |
現在,我們已經為控制項定義了事件,我們需要觸發該事件。我們計劃在DropDownList OnChange事件被觸發後觸發該事件。注意確保DropDownList控制項的AutPostBack屬性被設定為真。
(圖6)
下面是事件的代碼:
#code private void storeList_SelectedIndexChanged(object sender, System.EventArgs e) { data = (DataSet)Session["Data"]; OnStoreSelectorChanged( new StoreSelectorCommandEventArgs (data.Tables["stores"].Rows[storeList.SelectedIndex].ItemArray[0].ToString (), data.Tables["stores"].Rows[storeList.SelectedIndex].ItemArray[1].ToString( ), data.Tables["stores"].Rows[storeList.SelectedIndex].ItemArray[2].ToString(), data.Tables["stores"].Rows[storeList.SelectedIndex].ItemArray[3].ToString(), data.Tables["stores"].Rows[storeList.SelectedIndex].ItemArray[4].ToString(), data.Tables["stores"].Rows[storeList.SelectedIndex].ItemArray[5].ToString( ))); } #end code |
我們來分析一下在這裡所作的工作。當SelectedIndexChanged事件被觸發時,我將它傳遞給為控制項建立的新事件,我傳送的資料直接與填寫的dataset相關,所有條目都一個一個地被傳遞給StoreSelectorCommandEventArgs對象,然後觸發事件。
為了訪問Default.aspx網頁的新功能,我們需要在該類的OnInit部分添加事件處理常式:
(圖7)
如所示,StoreSelectorChanged事件出現在了Default.aspx網頁上。下面我們賦予它一個功能。我將在Default.aspx網頁上添加6個標籤,隨DropDownList的變化顯示值:
(圖8)
現在我們來編寫事件。
美觀是Intellisense是Intellisense認可定製的EventArg類屬性的原則:
(圖9)
最終的事件函數如下所示:
#code private void StoreSelector1_StoreSelectorChanged(object sender, Pubs.Controls.StoreSelectorCommandEventArgs e) { Label1.Text = e.stor_id; Label2.Text = e.stor_name; Label3.Text = e.stor_address; Label4.Text = e.city; Label5.Text = e.state; Label6.Text = e.zip; } #end code |
現在我們對該項目進行測試。該網頁一載入,讀者的頭腦中可能會閃現出這樣的念頭:它有問題,但我向你保證保證,該項目沒有任何問題。如果想在網頁一載入時就觸發該事件,我們必須通過設定DropDownList控制項中有選擇的索引屬性在已經建立的控制項中進行設定。
(圖10)
只要我們從DropDownList中選擇另一個Store,標籤就會發生變化:
(圖11)
現在我們使表單載入到第一個記錄。我們在StoreSelector控制項上添加下面的屬性:
#Code public int SelectedIndex { get{ return storeList.SelectedIndex; } set { if(!Page.IsPostBack) { BindData(); } if(value < storeList.Items.Count) { storeList.SelectedIndex = value; OnStoreSelectorChanged( new StoreSelectorCommandEventArgs (data.Tables["stores"].Rows[value].ItemArray[0].ToString(), data.Tables["stores"].Rows[value].ItemArray[1].ToString(), data.Tables["stores"].Rows[value].ItemArray[2].ToString(), data.Tables["stores"].Rows[value].ItemArray[3].ToString(), data.Tables["stores"].Rows[value].ItemArray[4].ToString(), data.Tables["stores"].Rows[value].ItemArray[5].ToString())); } } } #End Code |
然後設定Default.aspx中Page_Load事件的屬性:
#code private void Page_Load(object sender, System.EventArgs e) { // 使用者初始化網頁的代碼 if(!Page.IsPostBack) { StoreSelector1.SelectedIndex = 0; } } #end code |
運行該項目時,它就會將表單載入到第一個記錄。
小結
希望這篇文章能夠對廣大讀者有一定的協助。這種類型的Web應用程式的開發幾乎沒有什麼限制,只要設計得當,我們建立的每個Web控制項可以在整個Web應用程式中使用。