0

所以我有一个网格视图,我在后面的代码中填充,听一个下拉菜单来知道要填充什么。那部分工作正常。但是当我从 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>();
        }
    }
4

6 回答 6

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> 
于 2013-10-31T20:02:42.603 回答
1

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

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

你说你的函数在调用其他地方时有效,对吧?它仅适用于页面加载还是所选索引更改也有效?

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

于 2013-10-31T20:53:14.700 回答
0

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

于 2013-11-01T15:04:42.893 回答
0

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

于 2013-10-31T19:59:30.217 回答
0

您在此处将空值设置为 ListItem,这意味着您的下拉项将为 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 字符串的任何填充值。

于 2013-10-31T21:43:22.190 回答
0

想到别的东西,因为我意识到你的网格在更新面板中。您似乎遇到了与我之前遇到的问题类似的问题(不完全是,但似乎可能相关)Gridview Row 事件未在 UserControl 中触发

将网格从更新面板中取出并尝试一下,我敢打赌它会正常工作。我用来发现我的问题的参考是这里的链接

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

我发现 UpdatePanel 不值得,尤其是在处理此类问题时。如果您仍然打算使用它,请查看我的问题以了解我是如何解决问题的。它不是很漂亮,我的情况是处理动态控制,但也许它会有所帮助。

于 2013-11-01T14:20:51.240 回答