简体   繁体   English

重新绑定Gridview数据会引发NullReferenceException

[英]Rebinding Gridview Data Throws NullReferenceException

So I have a gridview that I'm populating in the code behind, listening to a drop down to know what to populate. 所以我有一个gridview,我在后面的代码中填充,听取下拉,知道要填充什么。 That part works fine. 那部分工作正常。 But when I fire the rowediting event from the gridview, the databind process throws a NullReferenceException error. 但是当我从gridview中触发rowediting事件时,databind进程会抛出NullReferenceException错误。

Here is the page: 这是页面:

<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>

And here is the code behind: 以下是代码背后的代码:

    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));
    }

The error occurs in the BindProductList() method, but only when called from gvProducts_RowEditing. 该错误发生在BindProductList()方法中,但仅在从gvProducts_RowEditing调用时发生。 Otherwise, it works fine. 否则,它工作正常。 When I debug, I can see that it definitely is passing the correct categoryID value, and it does not throw an error until the DataBind call, which means that it can still find gvProducts for the DataSource() call. 当我调试时,我可以看到它肯定传递了正确的categoryID值,并且在DataBind调用之前它不会抛出错误,这意味着它仍然可以找到DataSource()调用的gvProducts。

Any ideas? 有任何想法吗? Thanks. 谢谢。

Edit: here is the categorydb class and getcategories method. 编辑:这是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>();
        }
    }

I am not sure but i think you need this for each one of the columns i think you are missing the row to be edited 我不确定,但我认为你需要为每一列提供这个,我认为你错过了要编辑的行

 <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> 

i am not sure how you are calling the edit but i would sugest another column for it 我不确定你是如何调用编辑但我会为它添加另一列

<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> 

The other folks may have already solved your problem but here's another suggestion. 其他人可能已经解决了你的问题,但这是另一个建议。 I've had trouble with the SelectedValue attribute of ddl's before so you might try using: 我之前遇到过ddl的SelectedValue属性问题,所以你可以尝试使用:

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

You said that your function works when called other places though, right? 你说过,当你在其他地方打电话时你的功能有效,对吧? Does it only work on page load or does the selected index change work also? 它只适用于页面加载还是选定的索引更改也可以工作?

Out of curiosity, why are you using the ID from the ddl in the Edit event? 出于好奇,为什么要在Edit事件中使用ddl中的ID? I would think you would want to use the category derived from the row you are editing. 我认为你会想要使用从你正在编辑的行派生的类别。

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

You have an empty value set as a ListItem here which means that your Dropdown item will be Text="" and Value="" 这里有一个空值设置为ListItem,这意味着您的Dropdown项目将是Text =“”和Value =“”

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

There could be a possibility that your ddlCategories.SelectedValue is "". 您的ddlCategories.SelectedValue可能是“”。 If the ProductDB.GetProductsByCategory method doesn't come back with any records, it will bind a blank result set, and then try to throw the grid into edit mode on an index that no longer exists. 如果ProductDB.GetProductsByCategory方法没有返回任何记录,它将绑定一个空白结果集,然后尝试在不再存在的索引上将网格置于编辑模式。

Check that out and see if it gives you any insight into what might be happening there. 检查一下,看看它是否能让你深入了解那里可能发生的事情。

Typically I set my placeholder values in DropDownLists as 通常我将DropDownLists中的占位符值设置为

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

or 要么

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

Then before I do my value parsing I always can do an if statement to ensure they didn't select the placeholder value after selecting something is valid. 然后在我进行值解析之前,我总是可以执行if语句,以确保在选择有效的东西后它们没有选择占位符值。

In this case if you are always expecting an int , the first statement is probably the better option so you know you're never parsing a blank string or whatever filler value you use as a string as an int. 在这种情况下,如果你总是期望一个int ,那么第一个语句可能是更好的选择,所以你知道你永远不会解析一个空字符串或者你用作字符串作为int的任何填充值。

Thought of something else since I realize your grid is in an UpdatePanel. 因为我意识到你的网格在UpdatePanel中,所以想到别的东西。 It seems like you're having a similar problem to a problem I had before (not exactly but seems like it could be related) Gridview Row Events not firing in UserControl 看起来你遇到了类似问题我之前遇到过的问题(不完全是但似乎可能有关) Gridview Row事件没有在UserControl中触发

Take the Grid out of the update panel and try it, I bet it will work fine. 将Grid从更新面板中取出并尝试,我打赌它会正常工作。 The reference I used to find my problem was this link here 我曾经找到我的问题的提法是这个链接在这里

When your DataSource changes and you are rebinding on an async call, there is the potential for their IDs to be overwritten and therefore your ScriptManager loses the reference it had to the previous rows in the callback. 当您的DataSource发生更改并且您在异步调用上重新绑定时,可能会覆盖其ID,因此您的ScriptManager会丢失它对回调中前一行的引用。 Especially if your data source is changing. 特别是如果您的数据源正在发生变化

I've found that UpdatePanels are just not worth it, especially when dealing with problems like these. 我发现UpdatePanels不值得,特别是在处理这些问题时。 If you are still set on using it though, take a look at my question to find out how I managed to solve the problem. 如果您仍然开始使用它,请查看我的问题,以了解我是如何设法解决问题的。 It was not very pretty, and my situation dealt with dynamic controls, but maybe it will help. 它不是很漂亮,我的情况处理动态控制,但也许它会有所帮助。

Found it. 找到了。 The error was occurring in the ImageField column. 错误发生在ImageField列中。 The value from the database was null, which was apparently a problem when trying to edit. 数据库中的值为null,这在尝试编辑时显然是个问题。 It works fine when I comment out the ImageField. 当我注释掉ImageField时,它工作正常。 I'll have to figure out how to handle that. 我将不得不弄清楚如何处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM