FindControl() 返回空值

Posted

技术标签:

【中文标题】FindControl() 返回空值【英文标题】:FindControl() return null 【发布时间】:2012-01-25 06:32:33 【问题描述】:

我试图创建动态添加控件的应用程序。我有母版页,我的 asp:Content 在这里:

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<asp:ScriptManager ID="scriptManager1" runat="server">
</asp:ScriptManager>   
<div style="margin: 10px">
    <asp:UpdatePanel ID="updatePanel1" runat="server">
        <ContentTemplate>
            <asp:PlaceHolder runat="server" ID="myPlaceHolder" />
        </ContentTemplate>
        <Triggers>
            <asp:AsyncPostBackTrigger ControlID="btnAdd" EventName="Click" />
        </Triggers>
    </asp:UpdatePanel>
</div>
<asp:Button ID="btnAdd" runat="server" Text="Add" />

点击 btnAdd 后,我想添加两个文本框。我试着像http://jagdeepmankotia.wordpress.com/2010/01/30/dynamically-add-controls-in-asp-net-c/ 那样做

这是我的代码:

    static int myCount = 1;
    private TextBox[] color;
    private TextBox[] text;

    protected override void OnInit(EventArgs e)
    
        base.OnInit(e);
        color = new TextBox[myCount];
        text = new TextBox[myCount];

        for (int i = 0; i < myCount; i++)
        
            TextBox tbColor = new TextBox();
            tbColor.ID = "colorTextBox" + i.ToString();
            myPlaceHolder.Controls.Add(tbColor);
            color[i] = tbColor;

            TextBox tbText = new TextBox();
            tbText.ID = "textTextBox" + i.ToString();
            myPlaceHolder.Controls.Add(tbText);
            text[i] = tbText;

            LiteralControl literalBreak = new LiteralControl("<br />");
            myPlaceHolder.Controls.Add(literalBreak);
        
    


    public Control GetPostBackControl(Page page)
    
        Control control = null;
        string ctrlname = page.Request.Params.Get("__EVENTTARGET");
        if (ctrlname != null && ctrlname != string.Empty)
        
            control = page.FindControl(ctrlname);
        
        else
        
            foreach (string ctl in page.Request.Form)
            
                Control mycontrol = page.FindControl(ctl);
                if (mycontrol is System.Web.UI.WebControls.Button)
                
                    control = mycontrol;
                    // This gives you ID of which button caused postback                        
                    break;
                
            
        
        return control;
    

    protected void Page_PreInit(object sender, EventArgs e)
    
        Control myControl = GetPostBackControl(this.Page);
        if (myControl != null)
            if (myControl.ClientID.ToString() == "btnAdd")
                myCount = myCount + 1;
    

    protected void btnAdd_Click(object sender, EventArgs e)
    
        //handled in PreInit    

    

当在 loap foreach 中的函数 GetPostBackControl() 中寻找我的 btnAdd 时,例如在 ctr "ctl00$MainContent$scriptManager1" 的第一次迭代中,myControl 为空......在下一次迭代中也是......所以我的函数总是返回空值。可能是什么原因?

【问题讨论】:

【参考方案1】:

FindControl 仅搜索容器的直接子级。由于您是从页面级别开始的,因此您需要通过子 UpdatePanel 控件进行递归,以访问您的 btnAdd 控件。

查看here 以了解如何执行此操作的示例。

编辑: 我不确定我是否理解您为什么要以这种方式“寻找”您的按钮,因为屏幕上只有一个静态按钮 - 在这种情况下您不需要使用 FindControl

<asp:Button ID="btnAdd" runat="server" Text="Add" onclick="btnAdd_Click" />

(或在代码中,btnAdd.OnClick += new EventHandler(btnAdd_Click);

即使您在表单中动态添加了多个按钮,您也可以将它们全部连接到同一个按钮单击处理程序,在这种情况下,sender 将包含被单击的按钮控件。您通常会使用 FindControl 从动态添加的输入控件(文本框等)中抓取数据,而不是查看导致回发的控件(因为在适当的事件处理程序中“发送者”会更容易)

编辑 2: 您可以像其他控件一样动态添加按钮

    Button myButton = new Button();
    myButton.Text = "Click Me";
    myButton.Click += new EventHandler(btnAdd_Click);
    myPlaceHolder.Controls.Add(myButton); 

如果您希望已添加的所有控件在回发之间“停留”,则在页面和控件上启用视图状态,然后确保您只添加一次控件而无需回发,在 OnInit 中:

   base.OnInit(e);    
   if (!IsPostBack)
    // ... Add controls here

您可以将“mycount”的状态保留在隐藏字段中(在同一个更新面板中,并启用视图状态) - 您每次都需要将其解析为 int。或者你可以使用 SessionState 来跟踪它。

【讨论】:

感谢您的回答!稍后我将在此处添加第二个静态按钮,此处仅动态添加文本框。所以你认为我可以在这里使用 btnAdd_Click() 吗?我不知道,我怎样才能在按钮中增加 myCount,然后用 myCount 上的新值重新加载页面。你怎么看?

以上是关于FindControl() 返回空值的主要内容,如果未能解决你的问题,请参考以下文章

ASP.net .FindControl() 和 GridView 返回 null

在面板内的控件上使用 FindControl() 返回 null

C#,FindControl [重复]

FindControl 和 INamingContainer

FindControl的使用方法

Findcontrol 属性在 createUserWizard 中不起作用