台灣最大程式設計社群網站
線上人數
2032
 
會員總數:245249
討論主題:189109
歡迎您免費加入會員
討論區列表 >> 專欄文章 >> 撰寫Web自訂控制項的心得與範例
[]  
[我要回覆]
回應主題 加入我的關注話題 檢舉此篇討論 將提問者加入個人黑名單
撰寫Web自訂控制項的心得與範例
價值 : 0 QP  點閱數:1606 回應數:0

樓主

longer
高級專家
8502 27
5162 1946
發送站內信

捐贈 VP 給 longer
如果要在自訂控制項中再添加子控制項,應寫在哪堙H又要注意什麼?
一、override void CreateChildControls()
(一)子控件寫在這埵酗偵穧n處?
可直接加入ASP.NET的控件(也就是<ASP:XXX>),所有ASP.NET的控件中的事件.NETFrameWork會自己幫你加入,最基本的就是PostBack、Validate....的那些Javascript,這個優點就夠了。
如果要傳子控件的值出去,必須在override void OnLoad(EventArgs e)中取得。

(二)子控件寫在這埵酗偵艤a處?
很奇怪CreateChildControl事件,首次進入頁面時,是發生在Page_Load之後,但是當PostBack回來時,卻是發生在Page_Load之前。
所以外部引用的頁面,如果要透過自訂控件公開的屬性,改變CreateChildControl中加入的子控件(屬性、顯示或隱藏...),就不能寫在Page_Load,否則PostBack回來,外部設的新屬性會無效。
所以如果外部引用頁面要改變此處的子控件,寫在Page_Init,就不怕PoatBack回來又變回預設值。當然如果你沒有引發PostBack事件,那就可以寫在Page_Load無所謂。

二、override void RenderChildren or Render(HtmlTextWriter output)
(一)子控件寫在這埵酗偵穧n處?
所有公開屬性,在最後才生效,所以外部引用頁面要改變自訂控件中的屬性,寫在哪媕雩茬ㄞ鈳Q自訂控件收到。

(二)子控件寫在這埵酗偵艤a處?
所有子控件都得手動寫HTML Code叫HtmlTextWriter去輸出,非常麻煩,而且所有javascript事件都要自己寫,再加到子控件的Html Code中,要有一點功力且非常費時。
若要傳值,如果內部有Send的Button,可以自己寫事件解決(但自訂控制項,通常只是頁面的一部分,多半不負責Send網頁)
如果沒有Send的Button,就要實作IPostBackDataHanler,外部頁面才收得到,而這個介面實在是有點討厭,下面的例子中會說明。

子控件要寫在哪堙H各有利敝,依用途自行判斷了。
以下是:控制項建立位置與傳值的範例
範例連結:自訂Email控制項

自訂控制項程式碼

using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Reflection;
using System.Drawing;

[assembly: TagPrefix("Longer.WebControls","LWC")]
namespace Longer.WebControls
{

[ToolboxBitmap(typeof(SimpleEmailControl), "SimpleEmailControl.bmp")]
[DefaultProperty("Type")]
[ToolboxData("<{0}:SimpleEmailControl runat=server></{0}:SimpleEmailControl>")]
public class SimpleEmailControl : WebControl, INamingContainer, IPostBackDataHandler
{
#region private properities
private string EmailReg = @"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*";
private string _Sender = string.Empty;
private string _ReCeiver = string.Empty;
private Color _EmailBackColor = Color.White;
private Color _SenderBackColor = Color.White;
private string _ValidationGroup = string.Empty;
private string _PostBackEmailValue = string.Empty;
private TextBox EMailTbx = new TextBox();
/// <summary>
/// 取得收件者及寄件者姓名
/// </summary>
private String SenderAndReCeiver
{
//(實作IPostBackDataHandler時使用)
get
{
string s = (String)ViewState["Text"];
return ((s == null) ? String.Empty : s);
}
set { ViewState["Text"] = value; }
}
#endregion

public SimpleEmailControl()
{
}

#region Override Method

protected override void OnLoad(EventArgs e)
{
//(注意)==>CreateChildControls中的EMail文字方塊值要在OnLoad時取值,
//否則Page第一次PostBack會取不到值
if (Page.IsPostBack)//PostBack時才取值,否則使用外部給的預設值
this._PostBackEmailValue = this.EMailTbx.Text;
base.OnLoad(e);
}

protected override void CreateChildControls()
{
//(注意)==>在此處加入EMail,為的是使用驗證項,
//但EmailBackColor屬性,就必須在Page_Init中設定才有效
Literal txt = new Literal();
txt.Text = "收件者信箱:";

EMailTbx.Width =300;
EMailTbx.ValidationGroup = this._ValidationGroup;
EMailTbx.Text = this._PostBackEmailValue;
EMailTbx.ID = "REMailTbx";// 不可用變數;
EMailTbx.BackColor = this.EmailBackColor;

RequiredFieldValidator validA = new RequiredFieldValidator();
validA.ID = "EmailRequiredFieldValidator";
validA.ControlToValidate = EMailTbx.ID;
validA.ValidationGroup = this._ValidationGroup;
validA.ErrorMessage = "*";
validA.Display = ValidatorDisplay.Dynamic;

RegularExpressionValidator validB = new RegularExpressionValidator();
validB.ID = "EmailRegularValidator";
validB.ControlToValidate = EMailTbx.ID;
validB.ValidationGroup = this._ValidationGroup;
validB.ErrorMessage = "信箱格式錯誤";
validB.Display = ValidatorDisplay.Dynamic;
validB.ValidationExpression = this.EmailReg;

Controls.Add(txt);
Controls.Add(EMailTbx);
Controls.Add(validA);
Controls.Add(validB);

base.CreateChildControls();
}


protected override void Render(HtmlTextWriter output)
{
if (!(Site == null) && Site.DesignMode)
{
output.Write(string.Format("<font size='2' color='navy' face='arial'>[ \" EMailControl: {0}\" ]</font>
", this.ID));
output.Write("<font size='1' color='black' face='arial'> 不支援在VS.NET設計介面顯示</font>
");
}
else
{
//需實作IPostBackDataHandler,PostBack才能抓到文字方塊值
//(注意)==>實作IPostBackDataHandler,要傳出值的控件ID都必需使用this.UniqueID,才能抓得到。
//多個控件ID也都用this.UniqueID,會以,號分開各控件值
string patten="<INPUT type= 'text' name = '{0}' id='{0}' maxlength='30' value = '{1}'"
+" style=\"width:100px;background-color:"+System.Drawing.ColorTranslator.ToHtml(this._SenderBackColor)+";\" >";

output.Write(string.Format("寄件者姓名:" + patten, this.UniqueID, this._Sender));
output.Write(string.Format(" 收件者姓名:" + patten, this.UniqueID, this._ReCeiver));
}
base.Render(output);
}

#endregion

#region IPostBackDataHandler 成員
public delegate void EmailSend(object sender,EMailArgs e);
public event EmailSend OnEmailSend;
/// <summary>
/// Render()中之子控件傳送出來的值,且postCollection只蒐集ID是this.UniqueID控件的值
/// (注意)==>CreateChildContrl()中的控件值這塈鴗ㄗ
/// </summary>
/// <param name="postDataKey"></param>
/// <param name="postCollection"></param>
/// <returns></returns>
bool IPostBackDataHandler.LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
{
String presentValue = SenderAndReCeiver;//之前的值
//(注意)==>postCollection只蒐集ID是this.UniqueID控件的值
String postedValue = (string)postCollection[postDataKey];
if (postedValue != null)
{
if (!postedValue.Equals(presentValue))
{
SenderAndReCeiver = postedValue;
return true;
}
}
return false;
}


void IPostBackDataHandler.RaisePostDataChangedEvent()
{
EMailArgs arg = new EMailArgs();
arg.Reciver = this.ReCeiver;
arg.Sender = this.Sender;
arg.EMail = this._PostBackEmailValue;
doEmailSend(arg);
}
private void doEmailSend(EMailArgs e)
{
if (null != OnEmailSend)
OnEmailSend(this, e);
}
#endregion

#region Public Properties
/// <summary>
/// 信箱文字方塊背景色
/// </summary>
[Bindable(true)]
[Category("信箱屬性")]
[DefaultValue(typeof(Color), "White")]
[Description("信箱文字方塊背景色")]
[Localizable(true)]
public Color EmailBackColor
{
get { return _EmailBackColor; }
set { _EmailBackColor = value; }
}
/// <summary>
/// 信箱文字方塊背景色
/// </summary>
[Bindable(true)]
[Category("信箱屬性")]
[DefaultValue(typeof(Color), "White")]
[Description("寄件者文字方塊背景色")]
[Localizable(true)]
public Color SenderBackColor
{
get { return _SenderBackColor; }
set { _SenderBackColor = value; }
}

/// <summary>
/// 頁面Button驗證群組名稱(ValidationGroup)
/// </summary>
[Bindable(true)]
[Category("信箱屬性")]
[DefaultValue("ValidationGroup")]
[Description("指定ValidationGroup名稱")]
[Localizable(true)]
public string ValidationGroup
{
get { return _ValidationGroup; }
set { _ValidationGroup = value; }
}
/// <summary>
/// 取得收件者信箱
/// </summary>
[Bindable(true)]
[Category("信箱屬性")]
[DefaultValue("")]
[Description("取得收件者信箱")]
[Localizable(true)]
public string EMail
{
get { return this._PostBackEmailValue; }
set { this._PostBackEmailValue = value; }
}

/// <summary>
/// 取得寄件者姓名
/// </summary>
[Bindable(true)]
[Category("信箱屬性")]
[DefaultValue("")]
[Description("取得寄件者姓名")]
[Localizable(true)]
public String Sender
{
get
{
this._Sender = (SenderAndReCeiver != string.Empty) ? SenderAndReCeiver.Split(',')[0] : string.Empty;
return this._Sender;
}
set { this._Sender = value; }
}
/// <summary>
/// 取得收件者姓名
/// </summary>
[Bindable(true)]
[Category("信箱屬性")]
[DefaultValue("")]
[Description("取得寄件者姓名")]
[Localizable(true)]
public String ReCeiver
{
get
{
this._ReCeiver = (SenderAndReCeiver != string.Empty) ? SenderAndReCeiver.Split(',')[1] : string.Empty;
return this._ReCeiver;
}
set { this._ReCeiver = value; }
}
#endregion

}

/// <summary>
/// 事件Argument類別
/// </summary>
public class EMailArgs:EventArgs
{
public string EMail= string.Empty;
public string Sender = string.Empty;
public string Reciver = string.Empty;
public EMailArgs()
{
}
}
}


引用頁面aspx

<%@ Register Assembly="SimpleEmailControl" Namespace="Longer.WebControls" TagPrefix="LWC" %>
<LWC:SimpleEmailControl ID="SimpleEmailControl1" runat="server" ValidationGroup="emailgroup" />
<br />
<asp:Button ID="Button1" runat="server" Text="送出" ValidationGroup="emailgroup"
onclick="Button1_Click" />
<br />
<table>
<tr>
<td><asp:Label ID="Label1" runat="server" Text="Label"></asp:Label></td>
<td><asp:Label ID="Label2" runat="server" Text="Label"></asp:Label></td>
</tr>
</table>

後端程式碼aspx.cs

protected void Page_Init(object sender, EventArgs e)
{
//CreateChildControls事件中的子控制項屬性一定要在Page_Init設定,否則PostBack後,會重回預設值
SimpleEmailControl1.EmailBackColor = System.Drawing.ColorTranslator.FromHtml("#E7FAAB");
//設定與Button1相同的驗證群組
SimpleEmailControl1.ValidationGroup = Button1.ValidationGroup;
//if (!IsPostBack)
SimpleEmailControl1.EMail = "aaa@bbb.ccc";
//由SimpleEmailControl自己產生的事件取值(可做可不做)
SimpleEmailControl1.OnEmailSend+=new Longer.WebControls.SimpleEmailControl.EmailSend(SimpleEmailControl1_OnEmailSend);
}

protected void Page_Load(object sender, EventArgs e)
{
//Render事件中的子控制項屬性要在這堻]定即可
SimpleEmailControl1.SenderBackColor = System.Drawing.ColorTranslator.FromHtml("#E7FAAB");
if (!IsPostBack)
{
SimpleEmailControl1.Sender = "王小明";
SimpleEmailControl1.ReCeiver = "李大同";
}
}
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = string.Format("外部按鈕事件接收的值:
寄件者姓名:{0}
收件者姓名:{1}
收件者Email:{2}"
, SimpleEmailControl1.Sender
, SimpleEmailControl1.ReCeiver
, SimpleEmailControl1.EMail);
}
void SimpleEmailControl1_OnEmailSend(object sender, Longer.WebControls.EMailArgs e)
{
Label2.Text = string.Format("SimpleEmailControl的EmailSend事件傳出的值:
寄件者姓名:{0}
收件者姓名:{1}
收件者Email:{2}", e.Sender, e.Reciver, e.EMail);
}


搜尋相關Tags的文章: [ Web ] , [ Custom ] , [ Control ] , [ 自訂控制項 ] ,
本篇文章發表於2008-07-17 18:27
別忘捐VP感謝幫助你的人 新手會員瞧一瞧
目前尚無任何回覆
   

回覆
如要回應,請先登入.