You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET在Runat服务器端Div内查找控件遇空引用异常的解决方法

解决ASP.NET动态添加控件后FindControl空引用异常问题

问题分析

你通过后台代码动态向服务器控件d中添加了ul和li元素,但使用FindControl获取ul时出现空引用异常,无法修改li的class属性。核心原因通常有两个:

  • 动态控件未在PostBack时重新创建:ASP.NET不会自动保存动态添加的控件,PostBack后控件树中不存在该ul,导致FindControl返回null。
  • 控件添加时机晚于查找时机:如果查找操作的执行早于动态控件的添加逻辑,此时控件还未加入控件树,自然无法找到。

解决方案

方案1:确保动态控件在每次页面加载时都被创建

将动态创建ul和li的代码放在Page_Load事件中,并且不包裹在!IsPostBack判断内,这样每次页面加载(包括PostBack)都会重新创建并添加控件到控件树,保证FindControl能找到目标控件。

示例代码:

protected void Page_Load(object sender, EventArgs e)
{
    // 移除!IsPostBack判断,确保每次加载都创建动态控件
    string[] parole = { "morning", "good", "StackOverflow!" };
    string[] ordinalID = { "2", "1", "3" };
    string[] images = { "images/img-1.jpg", "images/img-2.jpg", "images/img-3.jpg" };

    HtmlGenericControl unorderedList = new HtmlGenericControl("ul");
    unorderedList.Attributes["class"] = "sortable-list";
    unorderedList.Attributes["id"] = "sortable";
    unorderedList.ClientIDMode = ClientIDMode.Static;

    Int16 i = -1;
    foreach (string parola in parole)
    {
        ++i;
       
        HtmlGenericControl listItem = new HtmlGenericControl("li");
        listItem.Attributes["class"] = "item";
        listItem.Attributes["id"] = ordinalID[i];
        listItem.Attributes["draggable"] = "true";
        listItem.ClientIDMode = ClientIDMode.Static;

        HtmlGenericControl div = new HtmlGenericControl("div");
        div.Attributes["class"] = "details";

        HtmlGenericControl img = new HtmlGenericControl("img");
        img.Attributes["src"] = images[i];

        HtmlGenericControl span = new HtmlGenericControl("span");
        span.InnerText = parola;

        HtmlGenericControl info = new HtmlGenericControl("i");
        info.Attributes["class"] = "uil uil-draggabledots";

        div.Controls.Add(img);
        div.Controls.Add(span);
        listItem.Controls.Add(div);
        listItem.Controls.Add(info);
        unorderedList.Controls.Add(listItem);
    }

    d.Controls.Add(unorderedList);
}

方案2:保存动态控件引用,避免使用FindControl

在创建li控件时,将其存入一个字典(键为控件ID,值为控件实例),后续需要修改时直接从字典中获取,无需调用FindControl,既高效又能避免空引用问题。

示例代码:

// 定义全局字典存储li控件引用
private Dictionary<string, HtmlGenericControl> _listItems = new Dictionary<string, HtmlGenericControl>();

protected void Page_Load(object sender, EventArgs e)
{
    string[] parole = { "morning", "good", "StackOverflow!" };
    string[] ordinalID = { "2", "1", "3" };
    string[] images = { "images/img-1.jpg", "images/img-2.jpg", "images/img-3.jpg" };

    HtmlGenericControl unorderedList = new HtmlGenericControl("ul");
    unorderedList.Attributes["class"] = "sortable-list";
    unorderedList.Attributes["id"] = "sortable";
    unorderedList.ClientIDMode = ClientIDMode.Static;

    Int16 i = -1;
    foreach (string parola in parole)
    {
        ++i;
       
        HtmlGenericControl listItem = new HtmlGenericControl("li");
        listItem.Attributes["class"] = "item";
        listItem.Attributes["id"] = ordinalID[i];
        listItem.Attributes["draggable"] = "true";
        listItem.ClientIDMode = ClientIDMode.Static;

        // 将li控件存入字典
        _listItems.Add(ordinalID[i], listItem);

        // 其余创建子控件的代码不变
        HtmlGenericControl div = new HtmlGenericControl("div");
        div.Attributes["class"] = "details";

        HtmlGenericControl img = new HtmlGenericControl("img");
        img.Attributes["src"] = images[i];

        HtmlGenericControl span = new HtmlGenericControl("span");
        span.InnerText = parola;

        HtmlGenericControl info = new HtmlGenericControl("i");
        info.Attributes["class"] = "uil uil-draggabledots";

        div.Controls.Add(img);
        div.Controls.Add(span);
        listItem.Controls.Add(div);
        listItem.Controls.Add(info);
        unorderedList.Controls.Add(listItem);
    }

    d.Controls.Add(unorderedList);
}

// 需要修改li class时直接从字典获取
public void UpdateListItemClass(string targetId)
{
    if (_listItems.ContainsKey(targetId))
    {
        _listItems[targetId].Attributes["class"] = "item bg-danger";
    }
}

方案3:递归查找控件(备用)

如果必须使用FindControl,可以实现一个递归查找的方法,确保能找到嵌套的控件:

private Control FindControlRecursive(Control parent, string id)
{
    if (parent.ID == id)
        return parent;

    foreach (Control child in parent.Controls)
    {
        Control foundControl = FindControlRecursive(child, id);
        if (foundControl != null)
            return foundControl;
    }

    return null;
}

// 使用方式
HtmlGenericControl ul = (HtmlGenericControl)FindControlRecursive(d, "sortable");
if (ul != null)
{
    HtmlGenericControl listItem = (HtmlGenericControl)FindControlRecursive(ul, targetOrdinalId);
    if (listItem != null)
    {
        listItem.Attributes["class"] = "item bg-danger";
    }
}

内容的提问来源于stack exchange,提问作者Gabriele Cozzolino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 10:17:10