代码之家  ›  专栏  ›  技术社区  ›  Claus Thomsen

ascx用户控件中的事件处理

  •  3
  • Claus Thomsen  · 技术社区  · 16 年前

    从用户控件到父控件/页的事件通信的最佳实践是什么?我想做类似的事情:

    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);
        }
    

    问题是什么是最佳实践?

    3 回复  |  直到 16 年前
        1
  •  6
  •   Doug Moore    16 年前

    您希望在父级中订阅的控件上创建一个事件。见 OdeToCode 举个例子。

    这篇文章是为了长寿:

    一些用户控件是完全独立的,例如,显示当前股票报价的用户控件不需要与页面上的任何其他内容交互。其他用户控件将包含要回发的按钮。尽管可以从包含页面订阅button click事件,但是这样做会破坏一些面向对象的封装规则。更好的方法是在用户控件中发布事件,以允许任何相关方处理该事件。

    这种技术通常被称为事件冒泡,因为事件可以继续通过层,从底部(用户控件)开始,并可能到达顶层(页面),就像一个气泡向上移动香槟杯一样。

    首先,让_s创建一个附加按钮的用户控件。

    <%@ 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方法来在事件触发时执行,就像用户控件为按钮触发Click事件时添加一个EventHandler一样。

    在onBubbleClick事件中,我们首先检查是否有人连接到该事件(BubbleClick!=null),然后我们可以通过调用BubbleClick、传递EventArgs参数并将用户控件(this)设置为事件发送者来调用所有事件处理方法。注意,我们也在使用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>");         
       }
    }
    

    注意,在初始化组件方法期间,父页只需要添加一个事件处理程序。当我们收到事件时,我们将再次使用reponse.write来跟踪执行流程。

    警告:如果在任何时候事件神秘地停止工作,请检查InitializeComponent方法以确保设计器没有删除任何添加事件处理程序的代码。

        2
  •  2
  •   Matias Nino    16 年前

    1)在用户控件中声明公共事件

    2)在用户控件内发布适当的RaiseEvent

    3)在父页的init事件中,使用addhandler将control.event分配给要使用的处理过程。

    很简单!

        3
  •  0
  •   Eric Barr    10 年前

    我在Odetocode上找到了与@Lordsklar在他接受的解决方案中所联系到的相同的解决方案。问题是我需要一个用VB而不是用C语言的解决方案。它翻译得不好。具体来说,检查onBubbleClick中的事件处理程序是否为空在VB中不起作用,因为编译器认为我正试图调用该事件,并给出了一个错误,该错误表示“…不能直接调用。使用一个“raiseEvent”语句来引发一个事件,“这是一个代码解决方案的VB翻译,使用一个名为CountryDropDownList的控件。

    首先,让_s创建一个附加了下拉列表的用户控件。

    <%@ Control Language="vb" AutoEventWireup="false" CodeBehind="CountryDropDownList.ascx.vb" Inherits="CountryDropDownList" %>
    <asp:DropDownList runat="server" ID="ddlCountryList" OnSelectedIndexChanged="ddlCountryList_SelectedIndexChanged" AutoPostBack="true">
        <asp:ListItem Value=""></asp:ListItem>
        <asp:ListItem value="US">United States</asp:ListItem>
        <asp:ListItem value="AF">Afghanistan</asp:ListItem>
        <asp:ListItem value="AL">Albania</asp:ListItem>
    </asp:DropDownList>
    

    用户控件的代码隐藏如下所示。

    Public Class CountryDropDownList
        Inherits System.Web.UI.UserControl
        Public Event SelectedCountryChanged As EventHandler
    
        Protected Sub ddlCountryList_SelectedIndexChanged(sender As Object, e As EventArgs)
            ' bubble the event up to the parent
            RaiseEvent SelectedCountryChanged(Me, e)
        End Sub
    End Class
    

    ASPX页面现在可以让用户控件工作。

    <%@ Page Language="vb" AutoEventWireup="false" CodeBehind="UpdateProfile.aspx.vb" Inherits="UpdateProfile" MaintainScrollPositionOnPostback="true" %>
    <%@ Register Src="~/UserControls/CountryDropDownList.ascx" TagPrefix="SO" TagName="ucCountryDropDownList" %>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
    <HTML>
        <HEAD>
            <title>WebForm1</title>
        </HEAD>
        <body>
            <form id="Form1" method="post" runat="server">
                <SO:ucCountryDropDownList id="ddlCountry" runat="server" />
            </form>
        </body>
    </HTML>
    

    在页面的代码隐藏中:

    Protected Sub OnSelectedCountryChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ddlCountry.SelectedCountryChanged
        ' add your code here
    End Sub