12

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

我已阅读On postback,如何在 Page_Init 事件 中检查哪个控件导致回发,以识别导致回发的控件(在 Page_Load 内)。但它不适用于我的场景。

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

注意:有关不可避免的另一种情况,请参阅以下内容https://codereview.stackexchange.com/questions/20510/custom-paging-in-asp-net-web-application

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

注意 2:我Request["__EVENTARGUMENT"]在 Page_Load 中得到空字符串

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

ASPX

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="PostbackTest.aspx.cs" Inherits="PostbackTest"
MasterPageFile="~/TestMasterPage.master" %>

<asp:Content ID="myContent" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<div id="holder" runat="server">
</div>
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="TestClick" />
</asp:Content>

代码背后

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. 如何从服务器控件中删除“名称”属性?
  7. 如何使用 __doPostBack()
4

4 回答 4

8

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

所以在你的情况下

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

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

    var btnTrigger = Request["__EVENTTARGET"]; 

     if(btnTrigger=="lnkDynamic123") 
{
}

--- 这将表明是您的链接按钮导致回发

于 2013-01-23T23:38:36.420 回答
4

在将 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 事件之后。

编辑:

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

于 2013-01-29T10:43:39.063 回答
2

如果您正确获取回发控件 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)重载,但我认为这很棘手。

另外,检查这个问题

于 2013-02-01T08:42:17.267 回答
2

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

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

默认情况下,此隐藏字段的值可能类似于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;
}
于 2013-02-01T13:01:16.623 回答