FindControl方法无法在页面上找到控件

时间:2009-10-27 14:08:51

标签: asp.net vb.net listview findcontrol

我已经尝试了几个小时,现在无法找出为什么我的代码(又名,我)失败了

基本上......我有一个listview控件,我正在传递产品的数据表(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 个答案:

答案 0 :(得分:5)

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

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

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

干杯,肖恩

答案 1 :(得分: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())

答案 2 :(得分:1)

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

我已经有一段时间了,因为我已经完成了大量的ASP.NET开发,但在我之前的经验中,我们总是使用服务器端控件并且没有问题。

答案 3 :(得分:0)

我注意到的另一件事是,如果子页面的ContentPlaceHolder嵌套在母版页上的LoginView内的LoggedInTemplate中,那么您可以忘记使用FindControl来获取子页面内控件的句柄。