在ASP.NET Repeater控件中找不到控件。

3
这让我感到困惑。我正在尝试在动态加载的asp.net Repeater模板中查找复选框。模板正常工作,数据绑定也正常,一切都正常显示,但我找不到控件!有什么想法吗?
这是repeater代码(我有一个类似的备用模板,具有不同的样式):
<%@ 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");

最后,这是我尝试查找复选框的方法(但一直返回null)

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>                    

5个回答

2

作为我的工具包的一部分,我有这个扩展方法:

    /// <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");

1

你为什么不实现 CheckBoxOnDataBinding 方法呢?

例如:

<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
@Dkong 不确定动态部分是否重要。你的 Repeater 组件有 ViewState 关闭吗?记住,如果您再次重新绑定(未检查 !IsPostBack),或者 ViewState 被关闭,则在回发时绑定的代码将消失,因此您必须在每个请求中重新绑定。 - Kelsey

0
你是否使用页眉/页脚模板?如果是,你需要检查ItemDataBound()被调用的模板类型。ItemDataBound()将被调用在每个模板上,包括页眉和页脚。存在HeaderTemplate将在调用后续ItemTemplates之前触发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

0

你应该查看生成的HTML,以确切地确定控件的位置。如果无法确定,可以通过迭代所有控件及其子控件来最终定位它。


0

我以前从未在代码后台中使用过设置模板,但是如果您生成的HTML包括像您指示的<ItemTemplate>这样的行,则某些地方可能存在问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接