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
相关产品推荐
相关产品推荐

