假设您有用户控件(ASCX):
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Test.ascx.cs"
Inherits="WebApplication1.Test" %>
<asp:Button ID="test" runat="server" OnClick="test_Click" Text="test" />
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication1
{
public partial class Test : System.Web.UI.UserControl
{
public event EventHandler Method1;
public EventHandler Method2
{
get { return (EventHandler)Session[this.ClientID + "|Method2"]; }
set { Session[this.ClientID + "|Method2"] = value; }
}
public EventHandler Method3
{
get { return (EventHandler)ViewState["Method3"]; }
set { ViewState["Method3"] = value; }
}
protected void test_Click(object sender, EventArgs e)
{
if (Method1 != null)
Method1(this, e);
if (Method2 != null)
Method2(this, e);
if (Method3 != null)
Method3(this, e);
}
}
}
你有一个页面可以放置UserControl:
<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master"
AutoEventWireup="true" CodeBehind="Default.aspx.cs"
Inherits="WebApplication1._Default" %>
<%@ Register Src="~/Test.ascx" TagName="Test" TagPrefix="uc1" %>
<asp:Content runat="server" ID="BodyContent" ContentPlaceHolderID="MainContent">
<uc1:Test ID="TestControl" runat="server" />
<asp:Label ID="Result" runat="server" Text="Test" />
</asp:Content>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication1
{
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
//Uncomment each one to observe their behavior
//Will never trigger(unless reset on each postback)
//if (!IsPostBack) TestControl.Method1 += new EventHandler(Test);
//Will trigger(the code will run) but makes no change to the parent page
//if (!IsPostBack) TestControl.Method2 += new EventHandler(Test);
/*
Will fail because it can't serialize the "EventHandler" object
You can play around by changing this to a delegate type
and making that serializable, but that fails as well
*/
//if (!IsPostBack) TestControl.Method3 += new EventHandler(Test);
}
protected void Test(object sender, EventArgs e)
{
Result.Text = Guid.NewGuid().ToString();
}
}
}
但是对于这个给定的用户控件,我们想要定义一个事件来捕获按钮的点击,并触发用户控件父母选择的事件。另外由于本例范围之外的要求,我们只想设置&#34; MethodX&#34;的值。 EventHandler一次,即不在每个Postback上重新创建控件/属性(在此示例中,我通过仅在页面加载上设置一次事件来演示此概念)。
如何实现这一目标?我尝试过的所有三种方法都以自己独特的方式失败了......到目前为止,我还没有找到与事件持续性相关的类似问题,大多数帖子都涉及变量/对象持久性(&#34) ;使用ViewState&#34;或其他各种持久化非事件对象的方法,请参阅link)或简单地指导用户在每个Postback(包括相关属性)上重新创建控件&#34; ,见link。
任何反馈或见解都会有所帮助,尤其令我感到困惑的是&#34; Method2&#34;的行为,我认为我对页面生命周期的理解不足以理解为什么发生了。
答案 0 :(得分:2)
您需要在加载事件之前注册事件(尝试初始化)。在init和load事件之间发生Click事件触发。
更新:抱歉,您在Load和LoadComplete之间引发了右键单击事件。
更新:我认为我找到了你需要的东西,令人失望的是,它不可能是你想要的。非静态方法的实例委托强烈依赖于方法类的实例。每个请求,页面实例都被创建,当请求结束时,它被处理掉。页面不是单例实例。这就是为什么,即使你将处理程序存储在会话中,它也无法重用,因为它试图从已处理的实例调用一个方法。
这是一篇关于事件和代表如何运作的好文章:http://csharpindepth.com/Articles/Chapter2/Events.aspx
最重要的部分是:
[..]任何特定委托实例中数据的关键点是委托引用的方法,以及在(目标)上调用方法的引用。对于静态方法,不需要目标。
target 是您创建的第一刻页面的页面/用户控件实例。当您进行回发时,页面/ usercontrol实例已更改,但您的持久化处理程序的目标未更改。