Protected override bool OnBubbleEvent(object source,EventArgs e){ 
bool handled=false; 
if(e is CommandEventArgs){ 
CommandEventArgs ce=(CommandEventArgs)e; 
If(ce.CommandName="Login"){ 
OnLogin(EventArgs.Empty); 
Handled=true; 
} 
} 
} 
那么我怎么知道OnBubbleEvent被初始化呢。如何把一个button事件上上传到顶层事件
呢。引发事件On方法中调用RaiseBubbleEvent方法。 
在button中OnCommand的内部实现。 
protected virtual void OnCommand(CommandEventArgs e) 
{ 
CommandEventHandler handler = (CommandEventHandler) base.Events[EventCommand]; 
if (handler != null) 
{ 
handler(this, e); 
} 
base.RaiseBubbleEvent(this, e); //这里冒泡事件传给顶层事件。 
} 
而我们知道RaiseBubbleEvent调用了OnBubbleEvent方法(参见前面)。。然后我们就去重写了OnBubbleEvnet 方法,让它去处理我们的逻辑,满足一个条件后。返回true; 
(四) 实现事件冒泡(事件上传)的步骤。 
 只要在自定义控件中,重写OnBubbleEvent方法,就能实现事件冒泡。因为在其子控件内部有一个OnCommand方法,它调用了RaiseBubbleEvent方法。而RaiseBubbleEvent调用了OnBubbleEvent方法。 
示例: 
protected override bool OnBubbleEvent(object sender,EventArgs e){
 bool handled = false; 
 if(e is CommandEventArgs) {
  CommandEventArgs ce = (CommandEventArgs)e; 
  if(ce.CommandName == "ButtonClick") { 
   OnButtonClick(EventArgs.Empty);
   handled =true;
  }
 }
 return handled;
} 
本节用到的示例控件代码:
示例代码
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.ComponentModel.Design;
using System.ComponentModel;
/**//// 
/// Class2 的摘要说明
/// 
/// 
namespace Cnblogs.Sui
{
 [DefaultEvent("Logon"),DefaultProperty("Name")]
 public class Class2 : WebControl,INamingContainer
 {
 private Button _button;
 private TextBox _nameTextBox;
 private Label _nameLabel;
 private Label _passwordLabel;
 private TextBox _passwordText;
 private RequiredFieldValidator _nameValidator;
 private RequiredFieldValidator _passwordValidtor;
 private static readonly object EventLogon=new object();
override properties#region override properties
 public override ControlCollection Controls
 {
 get { 
 EnsureChildControls();
 return base.Controls;
 }
 }
#endregion override properties
prorerties list#region prorerties list
 [Bindable(true),Category("Appearance"),DefaultValue(""),Description("The text to display on the button")]
 public string ButtonText
 {
 get{
 EnsureChildControls();
 return _button.Text;
 }
 set{
 EnsureChildControls();
 _button.Text=value;
 }
 }
 [Bindable(true),Category("default"),DefaultValue(""),Description("the user name")]
 public string Name{
 
 get{
 EnsureChildControls();
 return _nameTextBox.Text;
 
 }
 set{
 EnsureChildControls();
 _nameTextBox.Text=value;
 }
 }
 [Bindable(true),Category("Apearance"),DefaultValue(""),Description("Error Message of the validator used for the Name")]
 public string NameErrorMessage{
 
 get{
 
 EnsureChildControls();
 return _nameValidator.ErrorMessage;
 }
 set{
 EnsureChildControls();
 _nameValidator.ErrorMessage=value;
 _nameValidator.ToolTip=value;
 }
 }
 [Bindable(true),Category("Apperance"),DefaultValue(""),Description("the text for the name Label")]
 public string NameLabel
 {
 get{
 EnsureChildControls();
 return _nameLabel.Text;
 }
 set{
 EnsureChildControls();
 _nameLabel.Text=value;
 }
 }
 [Bindable(true),DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
 public string Password
 {
 
 get{
 EnsureChildControls();
 return _passwordText.Text;
 
 }
 }
 [Bindable(true),Category("Appearance"),DefaultValue(""),Description("Error Message of the validator used for the Password")]
 public string PasswordErrorMessage
 {
 get{
 EnsureChildControls();
 return _passwordValidtor.ErrorMessage;
 }
 set{
 EnsureChildControls();
 _passwordValidtor.ErrorMessage=value;
 _passwordValidtor.ToolTip=value;
 }
 }
 [Bindable(true),Category("Appearance"),DefaultValue(""),Description("the text for the password label")]
 public string PasswordLabel
 {
 get{
 
 EnsureChildControls();
 return _passwordLabel.Text;
 }
 set{
 
 EnsureChildControls();
 _passwordLabel.Text=value;
 }
 }
#endregion
events#region events
 [Category("Action"),Description("Raised when the user chicks the login button")]
 public event EventHandler Logon
 {
 add{
 
 Events.AddHandler(EventLogon,value);
 }
 remove{
 Events.RemoveHandler(EventLogon,value);
 }
 }
 public virtual void OnLogon(EventArgs e){
 
 EventHandler logonHandler=(EventHandler)Events[EventLogon];
 if(logonHandler !=null)
 {
 logonHandler(this,e);
 }
 }
#endregion
Event bubbling#region Event bubbling
 //the use of event bubbling in this seenario is somewhat contrived;
 //we have implemented it mainly for demostration purposes
 //in this case you could instead
 //raise the Logon event from an event handler wired to the 
 //click event or to the command event of the button control
 protected override bool OnBubbleEvent(object source, EventArgs e)
{
 bool handled=false;
 if(e is CommandEventArgs)
 {
 CommandEventArgs ce=(CommandEventArgs)e;
 if(ce.CommandName=="Logon")
 {
 OnLogon(EventArgs.Empty);
 handled=true;
 }
 }
 return handled;
}
#endregion
override methods#region override methods
 protected override void CreateChildControls()
{
 
 Controls.Clear();
 _nameLabel=new Label();
 _nameTextBox=new TextBox();
 _nameTextBox.ID="nameTextBox";
 _nameValidator=new RequiredFieldValidator();
 _nameValidator.ID="validator1";
 _nameValidator.ControlToValidate=_nameTextBox.ID;
 _nameValidator.Text="*";
 _nameValidator.Display=ValidatorDisplay.Static;
 _passwordLabel=new Label();
 _passwordText=new TextBox();
 _passwordText.TextMode=TextBoxMode.Password;
 _passwordText.ID="passwordTextBox";
 _passwordValidtor=new RequiredFieldValidator();
 _passwordValidtor.ID="validator2";
 _passwordValidtor.ControlToValidate=_passwordText.ID;
 _passwordValidtor.Text="*";
 _passwordValidtor.Display=ValidatorDisplay.Static;
 _button=new Button();
 _button.ID="button1";
 _button.CommandName="Logon";
 this.Controls.Add(_nameLabel);
 this.Controls.Add(_nameTextBox);
 this.Controls.Add(_nameValidator);
 this.Controls.Add(_passwordLabel);
 this.Controls.Add(_passwordText);
 this.Controls.Add(_passwordValidtor);
 this.Controls.Add(_button);
 
 base.CreateChildControls();
}
#endregion
 protected override void Render(HtmlTextWriter writer)
{
 
 AddAttributesToRender(writer);
 writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding,"1",false);
 writer.AddAttribute(HtmlTextWriterAttribute.Border, "1", false);
 writer.RenderBeginTag(HtmlTextWriterTag.Table);
 writer.RenderBeginTag(HtmlTextWriterTag.Tr);
 writer.RenderBeginTag(HtmlTextWriterTag.Td);
 _nameLabel.RenderControl(writer);
 writer.RenderEndTag();// TD
 writer.RenderBeginTag(HtmlTextWriterTag.Td);
 _nameTextBox.RenderControl(writer);
 _nameValidator.RenderControl(writer);
 writer.RenderEndTag();//TD
 writer.RenderEndTag();//TR
 writer.RenderBeginTag(HtmlTextWriterTag.Tr);
 writer.RenderBeginTag(HtmlTextWriterTag.Td);
 _passwordLabel.RenderControl(writer);
 writer.RenderEndTag();//TD
 writer.RenderBeginTag(HtmlTextWriterTag.Td);
 _passwordText.RenderControl(writer);
 
 _passwordValidtor.RenderControl(writer);
 writer.RenderEndTag();//TD
 writer.RenderEndTag();//tr
 writer.RenderBeginTag(HtmlTextWriterTag.Tr);
 writer.AddAttribute(HtmlTextWriterAttribute.Colspan,"2");
 writer.AddAttribute(HtmlTextWriterAttribute.Align,"center");
 writer.RenderBeginTag(HtmlTextWriterTag.Td); 
 
 _button.RenderControl(writer);
 writer.RenderEndTag();//td
 writer.RenderBeginTag(HtmlTextWriterTag.Td);
 // writer.Write(" ");
 writer.RenderEndTag();//td
 writer.RenderEndTag();//tr
 writer.RenderEndTag();//Table
 // base.Render(writer);
}
 public Class2()
 {
 //
 // TOD 在此处添加构造函数逻辑
 //
 }
 }
}