1

我已经尝试搜索了几个小时,但无法找出我的代码(又名我)失败的原因

基本上......我有一个列表视图控件,我正在传递产品的数据表(ID、名称、描述和价格列),并且我试图让它在按下“结帐”按钮时解析所有页面上的控件,找到具有正确 ID 的所有控件并将项目值添加到购物车。

我在源代码中检查了我的所有 ID,它们与 FindControl 方法请求的 ID 相匹配。

被抛出的错误是:

Object reference not set to an instance of an object.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 
Line 21:         For I = 1 To counter
Line 22:             Dim cartItem As New Core.Types.CartItem
Line 23:             cartItem.Name = CType(productsContainer.FindControl("product" + I.ToString()), HtmlGenericControl).InnerText
Line 24:             cartItem.Quantity = Convert.ToInt32(CType(productsContainer.FindControl("quantity" + I.ToString()), HtmlSelect).Value)
Line 25:             cartItem.Price = Convert.ToDecimal(CType(productsContainer.FindControl("price" + I.ToString()), HtmlGenericControl).InnerText.Remove(0, 1))

我的 .aspx 代码:

                <div class="productsContainer" id="productsContainer" runat="server">
                <asp:ListView runat="server" ID="lsvProducts">
                    <LayoutTemplate>
                        <ul class="lsvProducts">
                            <li class="highlight">
                                <div class="productName">
                                    Product
                                </div>
                                <div class="productQuantity">
                                    Number of Licenses
                                </div>
                                <div class="productPrice">
                                    Price
                                </div>
                            </li>
                            <asp:PlaceHolder ID="itemPlaceHolder" runat="server"></asp:PlaceHolder>
                        </ul>
                    </LayoutTemplate>
                    <ItemTemplate>
                        <li>
                        <div style="display: none;">
                            <%=setCurrent()%>
                        </div>
                        <input type="hidden" id='productID<%#Eval("ID")%>' />
                            <div class="productName" id='product<%=currentItem%>'>
                                <%#Eval("Name")%>
                            </div>
                            <div class="productQuantity">

                            <select id='quantity<%=currentItem%>'>
                                <option selected="selected"
                                value="0">0</option>
                                <option value="1">1</option>
                                <option value="2">2</option>
                                <option value="3">3</option>
                                <option value="4">4</option>
                                <option value="5">5</option>
                                <option value="6">6</option>
                                <option value="7">7</option>
                                <option value="8">8</option>
                                <option value="9">9</option>
                                <option value="10">10</option>
                            </select>
                            </div>
                            <div class="productPrice" id='price<%=currentItem%>'>
                                <%#"$" + Convert.ToDouble(Eval("Price")).ToString()%>
                            </div>
                        </li>
                    </ItemTemplate>
                </asp:ListView>
            </div>
            <div class="clearer">
                &nbsp;</div>
            <div class="purchaseButton">
                <asp:Button ID="btnAddCart" runat="server" Text="Add to Cart" />
            </div>
        </div>

和我背后的代码:

    Dim counter As Int32
Public currentItem As Int32

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    'get all active products to display in the listing
    Dim query As String = "SELECT * FROM Products WHERE Active = 1"
    Dim dt As DataTable = DAL.Data.GetDataTable(query, "MainDB")
    counter = dt.Rows.Count
    lsvProducts.DataSource = dt
    lsvProducts.DataBind()
End Sub

Protected Sub btnAddCart_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnAddCart.Click
    'create a new instance of the cart
    Dim cart As New Core.Types.Cart

    'foreach item in the listing, find its details and add it to the shopping cart
    For I = 1 To counter
        Dim cartItem As New Core.Types.CartItem
        cartItem.Name = CType(productsContainer.FindControl("product" + I.ToString()), HtmlGenericControl).InnerText
        cartItem.Quantity = Convert.ToInt32(CType(productsContainer.FindControl("quantity" + I.ToString()), HtmlSelect).Value)
        cartItem.Price = Convert.ToDecimal(CType(productsContainer.FindControl("price" + I.ToString()), HtmlGenericControl).InnerText.Remove(0, 1))
        cartItem.ID = Convert.ToInt32(CType(productsContainer.FindControl("productID" + I.ToString()), HtmlGenericControl).InnerText)
        cart.AddItem(cartItem)
    Next

    If (cart.isEmpty) Then
        'empty cart, go nowhere. show a message saying the carts empty and to choose something.
    Else
        Response.Redirect("~/Checkout.aspx")
    End If
End Sub

Public Function setCurrent()
    currentItem = currentItem + 1
    Return currentItem
End Function

请帮忙......这让我发疯了!

提前致谢 :)

4

4 回答 4

5

如果您在数据网格/中继器/列表视图中,要使用“FindControl”方法,您必须遍历列表视图中的数据项,然后为每个项目执行查找控制方法。例如在 C# 中:

foreach(RepeaterItem item in Repeater1.Items)
{
    Literal lit = (Literal)item.FindControl("controlId");
}

我不确定那是确切的语法,但你明白我的意思。您不能只在 listview Id 上使用 find 控件方法 - 每个项目中的服务器控件的 Id 都会被重写,因为您正在循环访问一个集合......

干杯,肖恩

于 2009-10-27T14:19:21.550 回答
5

FindControl 仅在当前命名容器中查找。如果您希望从不同的命名容器中查找控件,您应该有自己的(递归)实现。例如:

    private Control FindControlRecursive(Control parent, string id)
    {
        Control controlFound = parent.FindControl(id);
        int i = 0;
        while (controlFound == null && i < parent.Controls.Count)
        {
            controlFound = FindControlRecursive(parent.Controls[i++], id);
        }
        return controlFound;
    }

之后使用 FindControlRecursive(productsContainer, "product" + I.ToString())

于 2009-10-27T14:33:56.183 回答
1

看起来您的嵌套控件只是基本的 Html 控件?我不确定它们是否会在 ASP.NET 中注册,除非您有 runat="server" 将它们注册为服务器端控件。

自从我完成繁重的 ASP.NET 开发以来已经有一段时间了,但是根据我以前的经验,我们总是使用服务器端控件并且没有任何问题。

于 2009-10-27T14:37:00.780 回答
0

The other thing I noticed was that if your ContentPlaceHolder for a child page is nested inside a LoggedInTemplate inside a LoginView on a masterpage, then you can forget about using FindControl to grab the handle on a control inside the child page.

于 2010-07-16T22:42:48.420 回答