ascx用户控件中的事件处理
从用户控件向父控件/页面传达事件的最佳实践是什么,我想执行以下操作:
MyPage.aspx: <asp:Content ID="Content1" ContentPlaceHolderID="MainContentPlaceholder" runat="server"> <uc1:MyUserControl ID="MyUserControl1" runat="server" OnSomeEvent="MyUserControl_OnSomeEvent" /> MyUserControl.ascx.cs: public partial class MyUserControl: UserControl { public event EventHandler SomeEvent; .... private void OnSomething() { if (SomeEvent!= null) SomeEvent(this, EventArgs.Empty); }
问题是什么是最佳实践?
解决方案
1)在用户控件中声明一个Public事件
2)在用户控件内的适当位置发出RaiseEvent
3)在父页面的Init事件中,使用AddHandler将control.event分配给我们要使用的处理过程
就那么简单!
我们可能想在父级中订阅的控件上创建一个事件。有关示例,请参见OdeToCode。
为了长寿,这是这篇文章:
一些用户控件完全独立,例如,显示当前股票报价的用户控件不需要与页面上的任何其他内容进行交互。其他用户控件将包含要回发的按钮。尽管可以从包含页面订阅按钮单击事件,但是这样做会破坏某些面向对象的封装规则。更好的主意是在用户控件中发布事件,以允许任何感兴趣的方处理该事件。
这种技术通常称为事件冒泡,因为事件可以继续穿过图层,从底部开始(用户控件),然后可能到达顶层(页面),就像气泡在香槟杯中向上移动一样。
首先,让我们创建一个带有按钮的用户控件。
<%@ Control Language="c#" AutoEventWireup="false" Codebehind="WebUserControl1.ascx.cs" Inherits="aspnet.eventbubble.WebUserControl1" TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %> <asp:Panel id="Panel1" runat="server" Width="128px" Height="96px"> WebUserControl1 <asp:Button id="Button1" Text="Button" runat="server"/> </asp:Panel>
用户控件后面的代码如下所示。
public class WebUserControl1 : System.Web.UI.UserControl { protected System.Web.UI.WebControls.Button Button1; protected System.Web.UI.WebControls.Panel Panel1; private void Page_Load(object sender, System.EventArgs e) { Response.Write("WebUserControl1 :: Page_Load <BR>"); } private void Button1_Click(object sender, System.EventArgs e) { Response.Write("WebUserControl1 :: Begin Button1_Click <BR>"); OnBubbleClick(e); Response.Write("WebUserControl1 :: End Button1_Click <BR>"); } public event EventHandler BubbleClick; protected void OnBubbleClick(EventArgs e) { if(BubbleClick != null) { BubbleClick(this, e); } } #region Web Form Designer generated code override protected void OnInit(EventArgs e) { InitializeComponent(); base.OnInit(e); } private void InitializeComponent() { this.Button1.Click += new System.EventHandler(this.Button1_Click); this.Load += new System.EventHandler(this.Page_Load); } #endregion }
用户控件指定一个公共事件(BubbleClick),该事件声明一个委托。任何对BubbleClick事件感兴趣的人都可以添加EventHandler方法,以在事件触发时执行,就像用户控件为Button触发Click事件时添加事件处理程序一样。
在OnBubbleClick事件中,我们首先检查是否有人添加到该事件(BubbleClick!= null),然后我们可以通过调用BubbleClick,传递EventArgs参数并设置用户控件来调用所有事件处理方法(此)作为事件发送者。请注意,我们还使用Response.Write跟踪执行流程。
现在,ASPX页面可以使用户控件正常工作。
<%@ Register TagPrefix="ksa" TagName="BubbleControl" Src="WebUserControl1.ascx" %> <%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="aspnet.eventbubble.WebForm1" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" > <HTML> <HEAD> <title>WebForm1</title> </HEAD> <body MS_POSITIONING="GridLayout"> <form id="Form1" method="post" runat="server"> <ksa:BubbleControl id="BubbleControl" runat="server" /> </form> </body> </HTML>
在页面后面的代码中。
public class WebForm1 : System.Web.UI.Page { protected WebUserControl1 BubbleControl; private void Page_Load(object sender, System.EventArgs e) { Response.Write("WebForm1 :: Page_Load <BR>"); } #region Web Form Designer generated code override protected void OnInit(EventArgs e) { InitializeComponent(); base.OnInit(e); } private void InitializeComponent() { this.Load += new System.EventHandler(this.Page_Load); BubbleControl.BubbleClick += new EventHandler(WebForm1_BubbleClick); } #endregion private void WebForm1_BubbleClick(object sender, EventArgs e) { Response.Write("WebForm1 :: WebForm1_BubbleClick from " + sender.GetType().ToString() + "<BR>"); } }
注意,父页面只需要在InitializeComponent方法期间添加一个事件处理程序。当我们收到事件时,我们将再次使用Reponse.Write跟踪执行流程。
一句话警告:如果事件在任何时候都神秘地停止工作,请检查InitializeComponent方法,以确保设计者没有删除任何添加事件处理程序的代码。