【问题标题】:datalist in usercontrol throws nullreference exception while trying to assign datasource用户控件中的数据列表在尝试分配数据源时抛出空引用异常
【发布时间】:2012-01-06 00:37:24
【问题描述】:

我将一个 aspx 页面上的 Datalist 控件移到了一个用户控件上,并将它引用到了 aspx 页面。在此过程中,我还移动了数据列表的源代码(ItemDataBound 和 Display 方法)。我使用“数据表”作为 Datalist 人口的来源。在我将控件移入用户控件后,当我尝试将数据表作为源分配给数据列表时,它会给我一个 NullReference 权限。

public partial class Controls_ProductSpecifications : System.Web.UI.UserControl
{
    protected void Page_Load(object sender, EventArgs e)
    {
        //no code yet here...
    }

    public void DisplaySpecifications(SearchResultItem sri,bool IsMobilePage)
    {
        List<Category> breadcrumbCategories = sri.BreadcrumbCategories;
        Category templateCat =  breadcrumbCategories[breadcrumbCategories.Count - 1];

        ParametricColumnSortOrder customDimSortOrder = null;
        int rowPosition = 0; // manufacturer, product category, rohs
        bool isUnclassified = false;

        // -- get the sorted parametric list from database
        if (templateCat.Id.ToString() != null)
            customDimSortOrder = new ParametricColumnSortOrder(Convert.ToInt64(templateCat.Id), false, true);

        //List<ParametricAttributeGroup> plist = sri.ParametricDimensions;
        if (breadcrumbCategories[0].Name == "Unclassified")
        {
            ////if (breadcrumbCategories.Count > 1)
            ////{
            ////    //---{ Create an unclassifed attribute group } 
            ////    ParametricAttributeGroup pag = new ParametricAttributeGroup(breadcrumbCategories[0].Id, breadcrumbCategories[0].Name);
            ////    pag.ParametricAttributes.Add(new ParametricAttribute(breadcrumbCategories[1].Id, breadcrumbCategories[1].Name));
            ////    plist.Add(pag);
            ////}
        }

        var dt = new DataTable();
        dt.Columns.Add("Dimension");
        dt.Columns.Add("DimensionID");
        dt.Columns.Add("Attribute");
        dt.Columns.Add("AttributeID");
        dt.Columns.Add("CheckBox");
        dt.Columns.Add("CheckBoxState");

        DataRow dr;

        List<ParametricAttributeGroup> translatedAttGrp = sri.ParametricDimensions;

        LanguageDataAccess.GetTranslatedAttributes(translatedAttGrp, Language.CurrentLanguageCulture);

        foreach (ParametricAttributeGroup attributeGroup in translatedAttGrp)
        {
            ParametricAttribute attribute = attributeGroup.ParametricAttributes[0];

            dr = dt.NewRow();
            dr["Dimension"] = attributeGroup.Name;
            dr["DimensionID"] = attributeGroup.Id;
            dr["Attribute"] = attribute.Value;
            dr["AttributeID"] = attribute.Id;
            dr["CheckBox"] = "false";

            string grpname = attributeGroup.Name;
            // -- get the original name instead of the translated name for comparision --
            if (attributeGroup is LocalizationParametricAttributeGroup)
            {
                grpname = ((LocalizationParametricAttributeGroup)attributeGroup).OriginalName;
            }

            if (grpname == "Manufacturer")
            {
                dr["Dimension"] = Resources.MyMouser.lblManufacturer;
                dr["CheckBoxState"] = "0";
                dt.Rows.InsertAt(dr, rowPosition);
                rowPosition++;
            }
            else if (grpname == "Product Category")
            {
                // -- don't show product category if this product is under Unclassified --

                isUnclassified = breadcrumbCategories.Any(cat => cat.Name == Resources.MyMouser.lblUnclassified);

                if (!isUnclassified)
                {
                    dr["Dimension"] = attributeGroup.Name;
                    dr["Attribute"] = templateCat.Name;
                    dr["AttributeID"] = templateCat.Id;
                    dr["CheckBoxState"] = "0";
                    dt.Rows.InsertAt(dr, rowPosition);
                    rowPosition++;
                }
            }
            else if (grpname == "Unclassified")
            {
                dr["Dimension"] = Resources.MyMouser.lblUnclassified;
                dr["CheckBoxState"] = "0";
                dt.Rows.InsertAt(dr, rowPosition);
                rowPosition++;
            }
            else if (grpname == "RoHS - Mouser")
            {
                dr["Dimension"] = Resources.MyMouser.litHeaderRoHS;
                dr["Attribute"] = SearchHelper.CreateRoHSLabel(sri,sri.EnRoHSStatus, isUnclassified,IsMobilePage);
                dt.Rows.InsertAt(dr, rowPosition);
                rowPosition++;
            }
            else if (grpname == "Standard Pack Qty")
            {
                dr["Dimension"] = Resources.MyMouser.lblfactrPakcQty;
                dt.Rows.Add(dr);
            }
            else
            {
                dt.Rows.Add(dr);
            }
        }

        // -- sort the visiable fields --
        if (customDimSortOrder != null)
        {
            for (int dimSortIndex = 0; dimSortIndex < customDimSortOrder.Count; dimSortIndex++)
            {
                foreach (DataRow oldRow in dt.Rows)
                {
                    if (customDimSortOrder.AllKeys[dimSortIndex] == oldRow["DimensionID"].ToString())
                    {
                        dr = dt.NewRow();
                        dr["Dimension"] = oldRow["Dimension"];
                        dr["DimensionID"] = oldRow["DimensionID"];
                        dr["Attribute"] = oldRow["Attribute"];
                        dr["AttributeID"] = oldRow["AttributeID"];
                        dr["CheckBoxState"] = "0";
                        dt.Rows.Remove(oldRow);
                        dt.Rows.InsertAt(dr, rowPosition);
                        rowPosition++;
                        break;
                    }
                }
            }
        }

        //aliases information - shawn weng
        if (sri.Aliases != "")
        {
            dr = dt.NewRow();
            dr["Dimension"] = Resources.MyMouser.lblpartaliases;
            dr["DimensionID"] = 0;
            dr["Attribute"] = sri.Aliases;
            dr["AttributeID"] = 0;
            dr["CheckBox"] = "false";
            dt.Rows.Add(dr);
        }
        try
        {
            DataList dl1 = (DataList) this.FindControl("dlspec");
            dl1.DataSource = dt;
            dl1.DataBind();
        }
        catch (Exception ex)
        {
            throw;
        }

    }

    protected void dlspec_ItemDataBound(object sender, DataListItemEventArgs e)
    {
        if ((e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
            && e.Item.DataItem != null)
        {
            // -- checkbox --
            var ck = e.Item.FindControl("FindSimilarCheckbox") as CheckBox;
            if (ck != null)
            {
                ck.ID = ck.Text;
                ck.Text = "";

                var lbldim = e.Item.FindControl("lblDimension") as Label;
                if (lbldim != null)
                {
                    if (lbldim.Text.Contains(Resources.MyMouser.lblManufacturer) || lbldim.Text.Contains(Resources.MyMouser.lblProductCategory))
                    {
                        ck.Checked = true;
                    }
                    if (lbldim.Text.Contains(Resources.MyMouser.lblfactrPakcQty))
                    {

                        string PackageQtylnk = "<a href=JAVASCRIPT:OpenFactoryQty();>" + Resources.MyMouser.lblfactrPakcQty + "</a>";
                        lbldim.Text = string.Format(PackageQtylnk);
                        lbldim.CssClass = "factorypackage";
                    }
                }
            }
        }
    }
}

这是 ascx 页面标记:

<%@ Control Language="C#" AutoEventWireup="true"  CodeBehind="ProductSpecifications.ascx.cs" Inherits="MouserWeb.Controls.Controls_ProductSpecifications" %>
<asp:DataList ID="dlspec" runat="server" GridLines="Vertical" OnItemDataBound="dlspec_ItemDataBound">
    <FooterStyle BackColor="#CCCCCC" />
    <AlternatingItemStyle CssClass="alt-grey" />
    <SelectedItemStyle BackColor="#000099" Font-Bold="True" ForeColor="White" />
    <HeaderStyle BackColor="Black" Font-Bold="True" ForeColor="White" />
    <ItemTemplate>
        <table width="550px">
            <tr>
                <td class="leftcol">
                    <asp:Label ID="lblDimension" runat="server" Text='<%# Eval("Dimension") %>'></asp:Label>:
                </td>
                <td class="ProductDetailData">
                    <asp:Label ID="lblName" runat="server" Text='<%# Eval("Attribute") %>'></asp:Label>
                </td>
                <td class="find-similar">
                    <asp:CheckBox ID="FindSimilarCheckbox" runat="server" Checked='<%# Eval("CheckBox")=="true"? true:false %>'
                        Text='<%# Eval("AttributeID") %>' Visible='<%# Eval("CheckBoxState")=="0"? true:false %>' />
                    <%--<input name='<%# Eval("DimensionID") %>' id='<%# Eval("DimensionID") %>' type="checkbox" checked='<%# Eval("CheckBox")=="true"? true:false %>' />--%>
                </td>
            </tr>
        </table>
    </ItemTemplate>
</asp:DataList>

看起来有什么不对吗?请让我知道我是否可以提供有关此的更多信息(代码)...在此先感谢您的宝贵帮助

【问题讨论】:

  • 你在哪里实例化数据列表?
  • 我必须这样做吗?我上面粘贴的代码来自注册数据列表的用户控件的代码隐藏文件。我不能只取用户控件中声明的数据列表的 ID 并分配数据源吗?
  • 对不起...我的意思是数据表而不是数据列表。
  • 是的......我检查了一下......它不是空的......它里面有行。问题似乎出在数据列表本身的“dlspec”中..
  • 我刚刚检查并发现“dlspec”显示为空...我必须以某种方式启动它吗?

标签: c# asp.net user-controls datalist


【解决方案1】:

最可能的原因是没有设置dt

下一个最相似的原因是异常实际上是在dlspec_ItemDataBound 中引发的。

这就是为什么查看异常调用堆栈非常重要的原因,如果可用,请将其包含在您的问题中。

要从代码中捕获的异常中获取大量有用信息,可以调用它的 ToString 方法。例如,在你的 catch 块中:

Console.Write(ex.ToString();

更新

我对问题的根源有一个想法,这是我们多次遇到的问题(假设您正在使用 Web 应用程序项目):

如果您通过从页面/用户控件源中剪切和粘贴标记而不在进行更改后切换到设计模式,将控件从一个页面/用户控件移动到另一个页面/用户控件,Visual Studio 可以并不总是更新设计器文件中的引用。

如果您打开用户控件的设计器文件,您可以通过搜索 dlspec 来确认这一点。如果它不在那里,这就是问题的根源。

因为我们已经被这个打击过无数次了,每当我们像这样移动控件时,我们总是会切换到设计模式,弄脏一些东西,然后保存。为了安全起见,我们通常会仔细检查设计器文件,以确保之前的条目已被删除并重新读取新条目。

【讨论】:

  • 感谢您的回复...首先设置了 dt(我已经检查过了)...其次我还没有调用控件上的数据绑定,因此它不会转到 ItemDataBound 并且不会在那里抛出异常..我唯一的怀疑是“dlspec”出来为空?在尝试填充它之前,我是否必须做一些事情来实例化它?
  • 为我的问题添加了更多代码...你能看看它现在是否更有意义...再次感谢
  • -1:请添加“throw;”或以其他方式表明您并不真正打算让读者按原样复制此代码。那么我会删除downvote。
  • 抱歉,只是想显示调试代码(我们有集中的异常处理,所以重新抛出对我们来说从来不是一个问题,这就是我忘记包含它的原因)。已添加 throw。
  • @karry:用我认为可能解决您的问题的方法更新了答案。
【解决方案2】:

如果您的 DataList 显示为 null,则问题是 FindControl 未找到您的 datalist 控件的结果。这是 Scott Allen 关于这个主题的一个很好的article。如果 DataTable 为 null,那么它会在您的代码中的某处被清除。

试试这个来查明问题:

DataTable dt1 = dt; // Set breakpoint here; check dt1 and dl1 to pinpoint prob
DataList dl1 = (DataList) this.FindControl("dlspec");
dl1.DataSource = dt1;
dl1.DataBind();

在我在评论中指出的位置设置断点,然后逐步查看数据表是否为空。然后检查 FindControl 方法是否返回控件或是否为 null。

【讨论】:

  • -1 代表 try/catch/throw。如果您的意思是作为调试工具,那么请这样说并显示在哪里设置断点。然后,我将删除反对票。
  • @John 不,我不是说作为调试工具。那是用户的原始代码。我建议他将数据表设置为新的数据表并在那里设置断点,以便他可以确定数据表是否为空,然后逐步查看控件是否由查找控件方法返回。仅供参考 - 有一条评论告诉他在哪里设置断点。
  • 哎哟。他发布了这么多代码,我没有注意到。尽管如此,两个错误并不能成为一个正确的。请修正你的答案。
  • @JohnSaunders 听起来您在暗示这是对 try/catch 的不当使用(或至少是不必要的)。我同意,事实上,如果有任何安慰的话,我会尽量避免 try/catch 块,除非我打算将异常包装在某些东西中或作为异常的结果采取一些其他措施。显然,这里发生的不仅仅是错位的 try/catch 块——我试图专注于问题而不是挑剔那些家伙的代码。
  • 我不介意你不挑剔代码 - 只是不要重复 OP 的错误。
【解决方案3】:

我想我解决了这个问题... 因此,从用户控件注册到的 aspx 页面的 Page_load() 调用了 DisplaySpecification(...) 方法。 我将此调用移至 aspx 的 Page_PreRender() 事件,它运行良好。 原因是用户控件实际上直到 aspx page_load() 事件完成后才被加载。这就是为什么我一直将'dlspec'设为空。 感谢你们提供的所有帮助……你们太棒了。

再次感谢

【讨论】:

  • 虽然你不会得到任何分数,但你可以接受你自己的答案,以便快速向其他人提供你的问题已经解决的视觉提示。
  • 完成...对不起,我没有早点这样做
猜你喜欢
  • 2015-06-23
  • 1970-01-01
  • 2020-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-05
  • 2013-09-25
  • 1970-01-01
相关资源
最近更新 更多