C# ascx 用户控件中的事件处理

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/92860/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 11:35:19  来源:igfitidea点击:

Eventhandling in ascx usercontrols

提问by Claus Thomsen

What is best practises for communicating events from a usercontrol to parent control/page i want to do something similar to this:

将事件从用户控件传递到父控件/页面的最佳实践是什么我想做类似的事情:

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

Question is what is best practise?

问题是什么是最佳实践?

采纳答案by lordscarlet

You would want to create an event on the control that is subscribed to in the parent. See OdeToCodefor an example.

您可能希望在父级订阅的控件上创建一个事件。有关示例,请参阅OdeToCode

Here is the article for longevity sake:

这是为了长寿而写的文章:

Some user controls are entirely self contained, for example, a user control displaying current stock quotes does not need to interact with any other content on the page. Other user controls will contain buttons to post back. Although it is possible to subscribe to the button click event from the containing page, doing so would break some of the object oriented rules of encapsulation. A better idea is to publish an event in the user control to allow any interested parties to handle the event.

一些用户控件是完全自包含的,例如,显示当前股票行情的用户控件不需要与页面上的任何其他内容进行交互。其他用户控件将包含用于回发的按钮。尽管可以从包含页面订阅按钮单击事件,但这样做会破坏一些面向对象的封装规则。一个更好的主意是在用户控件中发布一个事件,以允许任何感兴趣的各方处理该事件。

This technique is commonly referred to as “event bubbling” since the event can continue to pass through layers, starting at the bottom (the user control) and perhaps reaching the top level (the page) like a bubble moving up a champagne glass.

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

For starters, let's create a user control with a button attached.

首先,让我们创建一个带有按钮的用户控件。

<%@ 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>

The code behind for the user control looks like the following.

用户控件背后的代码如下所示。

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

}

The user control specifies a public event (BubbleClick) which declares a delegate. Anyone interested in the BubbleClick event can add an EventHandler method to execute when the event fires – just like the user control adds an EventHandler for when the Button fires the Click event.

用户控件指定一个声明委托的公共事件 (BubbleClick)。任何对 BubbleClick 事件感兴趣的人都可以添加一个 EventHandler 方法以在事件触发时执行——就像用户控件为 Button 触发 Click 事件时添加一个 EventHandler 一样。

In the OnBubbleClick event, we first check to see if anyone has attached to the event (BubbleClick != null), we can then invoke all the event handling methods by calling BubbleClick, passing through the EventArgs parameter and setting the user control (this) as the event sender. Notice we are also using Response.Write to follow the flow of execution.

在 OnBubbleClick 事件中,我们首先检查是否有人附加到该事件(BubbleClick != null),然后我们可以通过调用 BubbleClick、传递 EventArgs 参数并设置用户控件(this)来调用所有事件处理方法作为事件发送者。请注意,我们还使用 Response.Write 来跟踪执行流程。

An ASPX page can now put the user control to work.

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>

In the code behind for the page.

在页面后面的代码中。

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

Notice the parent page simply needs to add an event handler during InitializeComponent method. When we receive the event we will again use Reponse.Write to follow the flow of execution.

注意父页面只需要在 InitializeComponent 方法中添加一个事件处理程序。当我们收到事件时,我们将再次使用 Reponse.Write 来跟踪执行流程。

One word of warning: if at anytime events mysteriously stop work, check the InitializeComponent method to make sure the designer has not removed any of the code adding event handlers.

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

回答by Matias Nino

1) Declare a Public event in the user control

1)在用户控件中声明一个Public事件

2) Issue a RaiseEvent where appropriate inside the user control

2) 在用户控件内适当的地方发出 RaiseEvent

3) In the Init event of the parent page, use AddHandler to assign the control.event to the the handling procedure you want to use

3)在父页面的Init事件中,使用AddHandler将control.event赋值给你要使用的处理程序

Simple as that!

就那么简单!

回答by Eric Barr

I found the same solution on OdeToCode that @lordscarlet linked to in his accepted solution. The problem was that I needed a solution in VB rather than C#. It didn't translate perfectly. Specifically, checking if the event handler is null in OnBubbleClick didn't work in VB because the compiler thought I was trying to call the event, and was giving an error that said "... cannot be called directly. Use a 'RaiseEvent' statement to raise an event." So here's a VB translation for the OdeToCode solution, using a control called CountryDropDownList.

我在 OdeToCode 上找到了与 @lordscarlet 在他接受的解决方案中链接的相同解决方案。问题是我需要 VB 而不是 C# 的解决方案。它没有完美翻译。具体来说,检查 OnBubbleClick 中的事件处理程序是否为 null 在 VB 中不起作用,因为编译器认为我正在尝试调用该事件,并给出了一个错误,指出“...无法直接调用。使用‘RaiseEvent’引发事件的声明。” 所以这里是 OdeToCode 解决方案的 VB 翻译,使用名为 CountryDropDownList 的控件。

For starters, let's create a user control with a dropdown attached.

首先,让我们创建一个带有下拉菜单的用户控件。

<%@ 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>

The code behind for the user control looks like the following.

用户控件背后的代码如下所示。

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

An ASPX page can now put the user control to work.

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>

In the code behind for the page:

在页面后面的代码中:

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