重新绑定Gridview数据会引发NullReferenceException

时间:2013-10-31 19:53:01

标签: c# asp.net gridview webforms

所以我有一个gridview,我在后面的代码中填充,听取下拉以了解要填充的内容。那部分工作正常。但是当我从gridview中触发rowediting事件时,数据绑定进程会抛出NullReferenceException错误。

以下是页面:

<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
        <ContentTemplate>

            <div id="categories">
                <h1>Categories</h1>
                <asp:DropDownList ID="ddlCategories" 
                    runat="server"
                    OnSelectedIndexChanged="ddlCategories_SelectedIndexChanged"          
                    AutoPostBack="true"></asp:DropDownList>
            </div>
            <div id="products">
                <h1>Products</h1>
                <asp:GridView ID="gvProducts" 
                    runat="server"
                    AutoGenerateColumns="false" 
                    OnRowEditing="gvProducts_RowEditing" 
                    AutoGenerateDeleteButton="True" 
                    AutoGenerateEditButton="True"
                    OnRowCancelingEdit="gvProducts_RowCancelingEdit"
                    OnRowUpdating="gvProducts_RowUpdating">
                    <Columns>
                        <asp:BoundField
                            DataField="Category.Name"
                            HeaderText="Category" />
                        <asp:BoundField
                            Datafield="Name" 
                            HeaderText="Name"/>
                        <asp:BoundField
                            Datafield="Description" 
                            HeaderText="Description"/>
                        <asp:BoundField
                            DataField="Price" 
                            HeaderText="Price"
                            DataFormatString="{0:c}" 
                            HtmlEncode="False"/>
                        <asp:ImageField
                            DataImageUrlField="ImageURL"
                            HeaderText="Picture"></asp:ImageField>
                        <asp:CheckBoxField
                            DataField="Active"
                            Text="Active" 
                            HeaderText="Status"/>
                    </Columns>
                </asp:GridView>
            </div>

        </ContentTemplate>
    </asp:UpdatePanel>

这是背后的代码:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            BindCategoryList();
            BindProductList();
        }
    }

    protected void BindCategoryList()
    {
        ddlCategories.DataTextField = "Name";
        ddlCategories.DataValueField = "CategoryID";
        ddlCategories.DataSource = CategoryDB.GetCategories();
        ddlCategories.DataBind();
        ddlCategories.Items.Insert(0, new ListItem(string.Empty));
        ddlCategories.SelectedIndex = 0;
    }

    protected void BindProductList(int categoryID = 0)
    {
        gvProducts.DataSource = ProductDB.GetProductsByCategory(categoryID);
        gvProducts.DataBind();
    }

    protected void ddlCategories_SelectedIndexChanged(object sender, EventArgs e)
    {
        BindProductList(Int32.Parse(ddlCategories.SelectedValue));
    }

    protected void gvProducts_RowEditing(object sender, GridViewEditEventArgs e)
    {
        gvProducts.EditIndex = e.NewEditIndex;
        BindProductList(Int32.Parse(ddlCategories.SelectedValue));
    }

错误发生在BindProductList()方法中,但仅在从gvProducts_RowEditing调用时发生。否则,它工作正常。当我调试时,我可以看到它肯定传递了正确的categoryID值,并且在DataBind调用之前它不会抛出错误,这意味着它仍然可以为DataSource()调用找到gvProducts。

有什么想法吗?感谢。

编辑:这是categorydb类和getcategories方法。

public class CategoryDB
{
    public static List<Category> GetCategories()
    {
        using (var db = new ProductContext())
        {
            return (from c in db.Categories
                    orderby c.Name
                    select c).ToList<Category>();
        }
    }

6 个答案:

答案 0 :(得分:1)

我不确定,但我认为您需要为每一列提供此功能,我认为您缺少要编辑的行

 <asp:TemplateField headertext="Category.Name">
          <ItemTemplate> <%#Eval("Category.Name")%></ItemTemplate>   
          <EditItemTemplate>
               <asp:TextBox id="txtCategory.Name" runat="server" Enabled="False" text='<%#Eval("Category.Name")%>'/>
          </EditItemTemplate>                
          <FooterTemplate>
         <asp:TextBox ID="Category.Name" runat="server">     </asp:TextBox>           
    </FooterTemplate >
      </asp:TemplateField> 

我不确定你是如何调用编辑的,但我会为它添加另一个列

<asp:TemplateField>
         <ItemTemplate>
              <asp:LinkButton ID="btnedit" runat="server" CommandName="Edit" Text="Edit"/>       
         </ItemTemplate>
          <EditItemTemplate>
              <asp:LinkButton ID="btnupdate" runat="server" CommandName="Update" Text="Update" />
              <asp:LinkButton ID="btncancel" runat="server" CommandName="Cancel" Text="Cancel"/>
              <asp:LinkButton ID="btnDelete" runat="server" CommandName="Delete" Text="Delete"/>
          </EditItemTemplate>
          <FooterTemplate>
            <asp:Button ID="btnInsert" runat="Server" Text="Insert" CommandName="Insert" UseSubmitBehavior="False" />
          </FooterTemplate>
      </asp:TemplateField> 

答案 1 :(得分:1)

其他人可能已经解决了你的问题,但这是另一个建议。我之前遇到过ddl的SelectedValue属性问题,所以你可以尝试使用:

BindProductList(Int32.Parse(ddlCategories.SelectedItem.Value));

你说你的功能在被叫到其他地方时起作用了,对吧?它只适用于页面加载还是选定的索引更改也可以工作?

出于好奇,你为什么要在编辑活动中使用ddl中的ID?我认为你会想要使用从你正在编辑的行派生的类别。

答案 2 :(得分:0)

您可能希望将GridViewEditEventArgs.Cancel属性设置为true。

答案 3 :(得分:0)

这里有一个空值设置为ListItem,这意味着您的Dropdown项目将是Text =“”和Value =“”

ddlCategories.Items.Insert(0, new ListItem(string.Empty));

您的ddlCategories.SelectedValue可能是“”。如果ProductDB.GetProductsByCategory方法没有带回任何记录,它将绑定一个空白结果集,然后尝试在不再存在的索引上将网格置于编辑模式。

检查一下,看看它是否能让你深入了解那里可能发生的事情。

通常我将DropDownLists中的占位符值设置为

ddlCategories.Items.Insert(0, new ListItem("Select a category", "0")) 

ddlCategories.Items.Insert(0, new ListItem("", "NULL"))

然后,在我进行值解析之前,我总是可以执行if语句,以确保在选择有效的内容后没有选择占位符值。

在这种情况下,如果你总是期待int,那么第一个语句可能是更好的选择,因此你知道你永远不会解析空字符串或你用作字符串作为int的任何填充值。

答案 4 :(得分:0)

因为我意识到你的网格在UpdatePanel中,所以想到别的东西。看起来你遇到的问题与我以前遇到过的问题类似(不完全相同,但似乎可能是相关的)Gridview Row Events not firing in UserControl

将Grid从更新面板中取出并尝试,我打赌它会正常工作。我用来查找问题的参考是这个链接here

当您的DataSource发生更改并且您正在重新绑定异步调用时,可能会覆盖其ID,因此您的ScriptManager会丢失它对回调中前一行的引用。特别是如果您的数据源正在发生变化。

我发现UpdatePanels不值得,特别是在处理这些问题时。如果您仍然开始使用它,请查看我的问题,以了解我是如何设法解决问题的。它不是很漂亮,我的情况涉及动态控制,但也许它会有所帮助。

答案 5 :(得分:0)

找到它。错误发生在ImageField列中。数据库中的值为null,这在尝试编辑时显然是个问题。 当我注释掉ImageField时,它工作正常。我必须弄清楚如何处理它。