Метод FindControl не может найти элемент управления на странице - PullRequest
1 голос
/ 27 октября 2009

Я пытался искать часы сейчас и не могу выяснить, почему мой код (иначе я) не работает

В основном ... У меня есть элемент управления списком, который я передаю в виде таблицы продуктов (столбцы ID, Имя, Описание и Цена), и я пытаюсь сделать так, чтобы при нажатии кнопки «Оформить заказ» анализирует все элементы управления на странице, находит все элементы управления с правильными идентификаторами и добавляет значения элементов в корзину.

Я проверил все мои идентификаторы в исходном коде, и они совпадают с теми, которые запрашиваются методом FindControl.

ошибка, возвращаемая назад:

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 ]

5 голосов
/ 27 октября 2009

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

5 голосов
/ 27 октября 2009

Если вы находитесь в сетке данных / ретрансляторе / просмотре списка, чтобы использовать метод «FindControl», вам придется перебирать элементы данных в представлении списка, а затем для каждого элемента выполнять метод управления поиском. например в C #:

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

Я не уверен, что это точный синтаксис, но вы понимаете, о чем я. Вы не можете просто использовать метод управления поиском в идентификаторе списка - идентификаторы серверных элементов управления в каждом элементе переписываются, потому что вы просматриваете коллекцию ...

Ура, Шон

1 голос
/ 27 октября 2009

Похоже, ваши вложенные элементы управления - это просто базовые элементы управления HTML? Я не уверен, что они будут зарегистрированы в ASP.NET, если у вас нет runat = "server", чтобы зарегистрировать их в качестве серверных элементов управления.

Прошло много времени с тех пор, как я много работал с ASP.NET, но в моем предыдущем опыте мы всегда использовали элементы управления на стороне сервера и не имели проблем.

0 голосов
/ 17 июля 2010

Еще одна вещь, которую я заметил, заключалась в том, что если ваш ContentPlaceHolder для дочерней страницы вложен в LoggedInTemplate внутри LoginView на главной странице, то вы можете забыть об использовании FindControl для захвата дескриптора элемента управления внутри дочерней страницы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...