【问题标题】:Unable to find control in asp.net Repeater control在asp.net中继器控件中找不到控件
【发布时间】:2010-08-23 17:52:07
【问题描述】:

这让我很困惑。我试图在动态加载的 asp.net 中继器模板中找到一个复选框。模板工作正常,数据绑定正常,一切正常,但我找不到控件!有什么想法吗?

这是中继器代码(我有一个类似的替代模板,但样式不同):

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="template-tasks-

incomplete.ascx.cs" Inherits="controls_template_tasks_incomplete" %>
<ItemTemplate>
    <div class="task">
        <div class="date"><asp:CheckBox ID="chkIsComplete" runat="server" 
                AutoPostBack="True" /><%# DataBinder.Eval(((RepeaterItem)Container).DataItem, "DateCreated")%></div>
        <div class="description"><%# DataBinder.Eval(((RepeaterItem)Container).DataItem, "TaskDescription")%></div>
    </div>                    
</ItemTemplate>

这就是我加载模板的方式(工作正常)

rptTasks.ItemTemplate = LoadTemplate("~/controls/template-tasks-incomplete.ascx");
        rptTasks.AlternatingItemTemplate = LoadTemplate("~/controls/template-tasks-incomplete-alt.ascx");

...最后这就是我尝试找到复选框的方式(但一直显示为空)

protected void rptTasks_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
    {
        CheckBox chkBoxIsComplete = (CheckBox)e.Item.FindControl("chkIsComplete");

        if (chkBoxIsComplete != null)
        {
            int taskID = (int)DataBinder.Eval(e.Item.DataItem, "TaskID");
        }
    }
}

我只能认为复选框在层次结构中的某处更深,但我不确定如何访问它,因为我认为 FindControl 会这样做。

这是生成的 HTML:

<ItemTemplate>
<div class="task">
    <div class="date"><input id="ctl00_ContentPlaceHolder1_rptTasks_ctl00_ctl00_chkIsComplete" type="checkbox" name="ctl00$ContentPlaceHolder1$rptTasks$ctl00$ctl00$chkIsComplete" onclick="javascript:setTimeout('__doPostBack(\'ctl00$ContentPlaceHolder1$rptTasks$ctl00$ctl00$chkIsComplete\',\'\')', 0)" />23/08/2010 11:53:00 PM</div>
    <div class="description">test task</div>
</div>                    

【问题讨论】:

    标签: asp.net repeater findcontrol


    【解决方案1】:

    我的工具包中有这个扩展方法:

        /// <summary>
        /// find the control with the given ID, recursively below the root
        /// </summary>
        public static Control FindControlRecursive( this ControlCollection root, string id )
        {
            foreach ( Control control in root )
            {
                if ( control != null && id.Equals( control.ID, StringComparison.InvariantCultureIgnoreCase ) )
                {
                    return control;
                }
                else
                {
                    Control result = FindControlRecursive( control.Controls, id );
                    if ( result != null )
                    {
                        return result;
                    }
                }
            }
    
            return null;
        }
    

    用法:

    CheckBox chkBoxIsComplete = (CheckBox)e.Item.Controls.FindControlRecursive("chkIsComplete");
    

    【讨论】:

      【解决方案2】:

      你为什么不实现CheckBox的OnDataBinding方法?

      例子:

      <asp:CheckBox ID="chkIsComplete" runat="server"
          AutoPostBack="True" OnDataBinding="chkIsComplete_DataBinding" />
      

      然后在您的代码隐藏中访问它:

      protected void chkIsComplete_DataBinding(object sender, System.EventArgs e)
      {
          CheckBox chk = (CheckBox)(sender);
          int taskID = (int)(Eval("TaskID"));
          // do whatever it is you need to do... you can use Eval to get any record value
          // of the current row and your sender is the actually control itself.
      }
      

      此代码将为每个数据绑定复选框运行,因此您可以做任何您需要做的事情,而不必关心寻找控件。通常这是进行数据绑定的最佳方式,因为它将您的代码范围限定为控制级别,因此您不必不断搜索所有内容并在记录级别硬编码搜索名称。

      【讨论】:

      • 这似乎适用于第一个绑定,但在复选框回发事件中它会丢失它 - 可能是因为它是一个动态加载的模板。
      • @Dkong 不确定动态部分是否重要。您是否为Repeater 关闭了ViewState?请记住,如果您再次重新绑定(不检查 !IsPostBack)或 ViewState 已关闭,因此您在每次请求时都重新绑定,绑定代码将会消失。
      【解决方案3】:

      您可能应该查看生成的 html 以确切了解控件的位置。除非您遍历所有控件及其子控件,否则您最终会找到它。

      【讨论】:

        【解决方案4】:

        我以前从未在代码隐藏中使用过设置模板,但似乎如果您生成的 HTML 包含 &lt;ItemTemplate&gt; 行,就像您指出的那样,那里的某些东西无法正常工作。

        【讨论】:

          【解决方案5】:

          您是否在使用页眉/页脚模板?如果是,则需要检查调用 ItemDataBound() 的模板类型。 ItemDataBound() 将在每个模板上调用,包括页眉和页脚。 HeaderTemplate 的存在将在随后的 ItemTemplate 上调用之前触发 ItemDataBound(),并且由于感兴趣的控件不包含在标题中,因此 FindControl() 将一无所获。通过仅在调用 ItemDataBound() 的项目类型是 Item/AlternatingItem 的情况下调用 FindControl(),您可以防止 null/Nothing 徒劳地返回搜索您的控件。

          <asp:Repeater ID="rpt" runat="server" OnItemDataBound="rpt_ItemDataBound">
          
          <HeaderTemplate><table><tr><td>Header</td></tr></HeaderTemplate>
          
          <ItemTemplate><tr><td><asp:button id="Button" runat="server"/></td></tr></ItemTemplate>
          
          <FooterTemplate><tr><td>Footer</td></tr></table></FooterTemplate>
          
          </asp:Repeater>
          
          Protected Sub rpt_ItemDataBound(sender As Object, e As System.Web.UI.WebControls.RepeaterItemEventArgs)
            If (e.Item.ItemType = ListItemType.Item) Or (e.Item.ItemType = ListItemType.AlternatingItem) Then
                Dim Button As Button = CType(e.Item.FindControl("Button"), Button)
            End If
          End Sub
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-12-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多