ASP.NET Repeater控件FindControl获取控件为Null的解决方法
解决Repeater控件FindControl返回Null的问题
1. 为HTML标签添加runat="server"属性
你的ASPX代码里,id_skill_user和frameworkName是普通HTML <label>标签,没有加上runat="server"属性——服务器端只会识别带这个属性的控件,所以用FindControl肯定拿不到它们。把这两个标签改成ASP.NET服务器控件:
<asp:Label ID="id_skill_user" runat="server" style="display: none;"><%# Eval("id_skill_user") %></asp:Label> <asp:Label ID="frameworkName" runat="server"><%# Eval("frameworkName") %></asp:Label>
2. 确保Repeater在回发时重新绑定数据
WebForms里的Repeater是数据绑定控件,每次回发都需要重建控件树。如果你的绑定逻辑只在首次加载(!IsPostBack)时执行,回发时控件树不会生成,Items集合为空,自然找不到控件。修改Page_Load里的绑定逻辑:
protected void Page_Load(object sender, EventArgs e) { // 不管是否回发,都重新绑定Repeater BindSkillRepeater(); } private void BindSkillRepeater() { // 替换成你实际获取数据源的代码 var skillUserList = GetSkillUserDataSource(); repeaterSkillUser.DataSource = skillUserList; repeaterSkillUser.DataBind(); }
如果数据源查询成本高,可以缓存到ViewState里,避免重复查库:
private void BindSkillRepeater() { if (ViewState["SkillUserList"] == null) { var skillUserList = GetSkillUserDataSource(); ViewState["SkillUserList"] = skillUserList; } repeaterSkillUser.DataSource = (List<SkillUserModel>)ViewState["SkillUserList"]; repeaterSkillUser.DataBind(); }
3. 修正异步事件的潜在问题
你用了async void作为按钮点击事件的返回值,WebForms里这种写法可能导致页面生命周期异常(异步操作没完成页面就结束了)。建议改成async Task,同时确保页面启用异步:
在ASPX页面顶部的Page指令里加Async="true":
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="YourPage.aspx.cs" Inherits="YourNamespace.YourPage" Async="true" %>
然后修改按钮事件:
protected async Task ButtonOk_Click(object sender, EventArgs e) { if (Page.IsValid) { string id = Request.QueryString["id"]; foreach (RepeaterItem item in repeaterSkillUser.Items) { if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem) { Label idLabel = item.FindControl("id_skill_user") as Label; Label frameworkNameLabel = item.FindControl("frameworkName") as Label; DropDownList dropdown = item.FindControl("ListLevel") as DropDownList; TextBox textbox = item.FindControl("InputValue") as TextBox; // 先判断控件是否为空,避免空引用报错 if (idLabel == null || dropdown == null || textbox == null) continue; SkillUserModel data = new SkillUserModel { level = "Random", value = textbox.Text.ToInt() }; var response = await skillUserController.Update(idLabel.Text, data); // WebForms里别用Console.WriteLine,换成日志组件或页面提示 if (response.IsSuccessStatusCode) { // 比如记录到日志:Logger.Info("数据更新成功"); } else { // Logger.Error($"更新失败:{response.StatusCode} - {response.ReasonPhrase}"); } } } } }
4. 额外检查点
- 确认Repeater的ID在ASPX和后台代码里完全一致(大小写敏感)。
- 检查ItemTemplate里有没有嵌套服务器控件(比如
<asp:Panel>),如果有,需要先找到父容器再找子控件。 - 确保页面ViewState没有被禁用(默认是启用的),禁用后回发时控件状态会丢失。
内容的提问来源于stack exchange,提问作者Dima Keda
相关产品推荐
相关产品推荐

