如何检查动态链接按钮引起的回发

我有一个按钮控件。 单击此按钮,我需要动态添加链接按钮。 链接按钮需要一个事件处理程序。 因此,动态链接按钮首先添加到Page_Load中,然后在按钮单击处理程序中清除并再次添加。 请阅读Dynamic Control的事件处理程序的工作,以了解此操作的业务需求。

我已阅读On backback,如何检查哪个控件导致Page_Init事件中的回发以识别导致回发的控件(在Page_Load内)。 但它不符合我的情况。

需要做些什么更改才能确认回发是否是由链接按钮(在Page_Load内)引起的?

注意 :请参阅以下内容以了解其中不可避免的情况https://codereview.stackexchange.com/questions/20510/custom-paging-in-asp-net-web-application

注1: if (Page.IsPostBack)我需要将回发控件ID作为内部的第一步。 我需要添加动态链接按钮控件,只有它是从按钮或链接按钮的回发。 将有其他控件导致回发。 对于此类回发,我们不应该执行此代码。

注2:我在Page_Load中获取Request["__EVENTARGUMENT"]空字符串

相关问题 :在什么情况event ,动态控件将在页面中可用(用于在FindControl中使用)。 @Tung说 – “你的GetPostBackControlId方法正确获取导致回发的控件的名称,但它无法通过page.FindControl找到具有该id的控件,因为尚未创建链接按钮,因此页面不会知道它的存在。“

ASPX

   

代码背后

 public partial class PostbackTest : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if(Page.IsPostBack) { string IDValue = GetPostBackControlId(this.Page); int x = 0; holder.Controls.Clear(); LinkButton lnkDynamic = new LinkButton(); lnkDynamic.Click += new EventHandler(LinkClick); lnkDynamic.ID = "lnkDynamic123"; lnkDynamic.Text = "lnkDynamic123"; holder.Controls.Add(lnkDynamic); } } protected void TestClick(object sender, EventArgs e) { holder.Controls.Clear(); LinkButton lnkDynamic = new LinkButton(); lnkDynamic.Click += new EventHandler(LinkClick); lnkDynamic.ID = "lnkDynamic123"; lnkDynamic.Text = "lnkDynamic123"; holder.Controls.Add(lnkDynamic); } protected void LinkClick(object sender, EventArgs e) { } public static string GetPostBackControlId(Page page) { if (!page.IsPostBack) { return string.Empty; } Control control = null; // First check the "__EVENTTARGET" for controls with "_doPostBack" function string controlName = page.Request.Params["__EVENTTARGET"]; if (!String.IsNullOrEmpty(controlName)) { control = page.FindControl(controlName); } else { // if __EVENTTARGET is null, the control is a button type string controlId; Control foundControl; foreach (string ctl in page.Request.Form) { // Handle ImageButton they having an additional "quasi-property" in their Id which identifies mouse x and y coordinates if (ctl.EndsWith(".x") || ctl.EndsWith(".y")) { controlId = ctl.Substring(0, ctl.Length - 2); foundControl = page.FindControl(controlId); } else { foundControl = page.FindControl(ctl); } if (!(foundControl is Button || foundControl is ImageButton)) continue; control = foundControl; break; } } return control == null ? String.Empty : control.ID; } } 

参考

  1. 在回发时,如何检查哪个控件导致Page_Init事件中的回发
  2. 动态控制的事件处理程序的工作
  3. 了解JavaScript __doPostBack函数
  4. 使用ASP.NET代码在PostBack上访问JavaScript变量
  5. ASP.NET如何知道在回发期间要触发哪个事件?
  6. 如何从服务器控件中删除’name’属性?
  7. 如何使用__doPostBack()

asp.net中的回发是由java脚本函数__doPostback(source,parameter)完成的

所以在你的情况下它会

  __doPostback("lnkDynamic123","") something like this 

所以在后面的代码中执行以下操作

  var btnTrigger = Request["__EVENTTARGET"]; if(btnTrigger=="lnkDynamic123") { } 

—这会告诉你导致回发的是你的链接按钮

将LinkBut​​ton添加到页面 ,您可以将调用移动到GetPostBackControlId方法:

 protected void Page_Load(object sender, EventArgs e) { if (Page.IsPostBack) { holder.Controls.Clear(); LinkButton lnkDynamic = new LinkButton(); lnkDynamic.Click += new EventHandler(LinkClick); lnkDynamic.ID = "lnkDynamic123"; lnkDynamic.Text = "lnkDynamic123"; holder.Controls.Add(lnkDynamic); string IDValue = GetPostBackControlId(this.Page); if (IDValue == lnkDynamic.ID) LinkClick(lnkDynamic, new EventArgs()); } } 

在这里调用click事件处理程序也更接近于模仿标准的ASP.NET页面生命周期,其中Postback事件处理发生在Load事件之后。

编辑:

如果必须在创建LinkBut​​tons 之前确定控件ID,则可以为链接按钮ID创建命名方案,例如lnkDynamic_1,lnkDynamic_2等。 Request["__EVENTTARGET"]将包含自动生成的控件ID,例如“ctl00” $ mc $ lnkDynamic_1“,您可以使用它来识别哪个LinkBut​​ton导致回发。

如果你正确地获得了回发控制ID但FindControl没有返回任何内容,那么可能是因为你正在使用母版页。 基本上, someControl.FindControl(id)搜索someControl.NamingContainer命名容器中的控件。 但在您的情况下, Button1控件位于ContentPlaceHolder1 ,它是一个命名容器,而不是直接在Page命名容器中,因此您不会通过调用Page.FindControl找到它。 如果您无法预测您正在寻找的控件将在哪个命名容器中(例如,回发可能是由来自两个不同内容占位符的两个不同按钮引起的),那么您可以编写一个扩展名来搜索递归控件,如下所示:

 public static class Extensions { public static Control FindControlRecursively(this Control control, string id) { if (control.ID == id) return control; Control result = default(Control); foreach (Control child in control.Controls) { result = child.FindControlRecursively(id); if (result != default(Control)) break; } return result; } } 

但请谨慎使用它,因为此方法将返回它使用指定id找到的第一个控件(并且您可以使用具有相同id的多个控件 – 但它们位于不同的命名容器中;命名容器用于区分控件使用相同的ID,就像名称空间用于区分具有相同名称的类一样)。

或者,您可以尝试使用FindControl(string id, int pathOffset)重载,但我认为这非常棘手。

另外,请检查此问题 。

第一种方法(不推荐,但更灵活)

一种完全不同的方法 – 虽然我真的不觉得我应该推广它 – 是为表单添加隐藏字段。

默认情况下,此隐藏字段的值可能类似于false

如果单击其中一个动态按钮会导致再次添加动态控件,您可以在执行回发之前在客户端将隐藏字段值更改为true (最终您希望/必须修改客户端onclick处理程序实现这一目标)。

当然,可以在这样的字段中存储更多信息,例如控件ID和参数(但是您可以按照其他答案中的描述获取这些值)。 在这种情况下,不需要命名模式。

这个隐藏的字段可能是“静态的”。 所以它始终可以在代码中访问。 无论如何,你可能想要实现一些东西,以确保没有人正在玩它的值并伪造一个回调,看起来它起源于这些动态链接之一。

但是,这整个方法只是帮助您获取控件的ID。 在再次创建控件之前,您将无法通过NamingContainer.FindControl获取实例(如已在其他答案中提到的那样;))。 如果你创建它,你不再需要找到它。

第二种方法(由于其约束可能不合适)

如果你想以干净的方式做到这一点,你需要创建你的控件OnLoad,无论是否点击了什么。 此外,动态控件ID必须与您首先发送给客户端的ID相同。 您订阅其Click或Command事件并将其可见性设置为false。 在click事件处理程序中,您可以再次将发件人可见性设置为true。 这意味着,您不关心是否创建了该链接,而只是不想将其发送到客户端。 以下示例当​​然仅适用于单个链接(但您可以轻松修改它以覆盖整组链接)。

 public void Page_Load(object sender, EventArgs e) { LinkButton dynamicButton = new LinkButton(); dynamicButton.ID = "linkDynamic123"; // this id needs to be the same as it was when you // first sent the page containing the dynamic link to the client dynamicButton.Click += DynamicButton_Click; dynamicButton.Visible = false; Controls.Add(dynamicButton); } public void DynamicButton_Click(object sender, EventArgs e) { // as you created the control during Page.Load, this event will be fired. ((LinkButton)sender).Visible = true; }