Find control inside footer of nested repeater? (.NET 2.0 , C#)

7.2k views Asked by At

I'm getting null reference errors when looking for a quantity box control in the footer of a nested repeater. The error occurs when OnItemCommand function is executed (not when data is being bound to the repeater, which was an issue I encountered before but fixed).

I'm a newbie, so I don't understand all of this, and I'm trying to work through it as I go, but I don't know why FindControl inside of a foreach repeateritem (which msdn says includes the header and footer of a repeater!) wouldn't find the control in the footer of that repeater. It's driving me nuts.

Please help!

UPDATE: I changed the code but am still having the same issue-- I am referencing the ddl incorrectly and I keep getting object reference not set to an instance of an object.

Here's the code:

.NET:

    <asp:Content ID="ProductRepeater" ContentPlaceHolderID="ProductRepeater" Runat="Server">
  <asp:Repeater ID="chairRepeater" OnItemCommand="productRepeater_ItemCommand" OnItemDataBound="chairRepeater_ItemDataBound" runat="server">
    <ItemTemplate>
      ...
      <asp:Repeater ID="variantRepeater" OnItemDataBound="variantRepeater_ItemDataBound" runat="server">
        <ItemTemplate>
          <li>
            <asp:RadioButton ID="radioBtn" GroupName="collections" runat="server"></asp:RadioButton>
            <asp:HiddenField ID="variantId" runat="server" />
            <asp:Literal ID="Image1" runat="server" />
            &nbsp;
            <asp:Literal ID="collectionName" runat="server" />
            &nbsp;&ndash;&nbsp;
            <asp:Literal ID="listPrice" runat="server" />
          </li>
        </ItemTemplate>
        <FooterTemplate>
        </ul>
          <asp:DropDownList ID="quantityLister" runat="server" />
        </FooterTemplate>
      </asp:Repeater>
         <asp:ImageButton ID="addToCart" ImageUrl="assets/images/_addtocart.gif"  runat="server" />
      </div>
      </div>
    </ItemTemplate>
    <SeparatorTemplate> <br />
    </SeparatorTemplate>
    <FooterTemplate> </FooterTemplate>
  </asp:Repeater>

C#:

protected void productRepeater_ItemCommand(object source, RepeaterCommandEventArgs e)
{
    BasketHelper basketHelper = new BasketHelper(SiteContext.Current.ShoppingBasketName);
    OrderForm orderForm = basketHelper.GetOrderForm();
    bool basketUpdated = false;

    string catalogName = ConfigurationManager.AppSettings["PatioCatalogName"];
    string productId = ((HiddenField)e.Item.FindControl("productId")).Value;
    string variantId = "";

    Repeater variantRepeater = (Repeater)e.Item.FindControl("variantRepeater");
    foreach (RepeaterItem item in variantRepeater.Items)
    {
        RadioButton radioBtn = item.FindControl("radioBtn") as RadioButton;

        if (radioBtn.Checked == true)
        {
            variantId = ((HiddenField)item.FindControl("variantId")).Value;
        }
    }
        int quantity = 0;
        DropDownList quantityLister = (DropDownList)variantRepeater.FindControl("quantityLister");
        string ddlvalue = quantityLister.SelectedValue;
        int.TryParse(ddlvalue, out quantity);

        if (quantity > 0)
        {
            orderForm.LineItems.Add(new LineItem(catalogName, productId, variantId, quantity));
            basketUpdated = true;
        }
    if (basketUpdated)
    {
        basketHelper.Basket.Save();

        Response.Redirect(
            String.Format(
                CultureInfo.InvariantCulture,
                "~/cart.aspx?{0}={1}",
                SiteConstants.ActionQueryStringKey,
                SiteConstants.RunPipelineCartAction),
            true);
    }
}

And here's the error I get when I press my buy button:

Server Error in '/' Application.
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.

Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.

Source Error:

Line 116:            int quantity = 0;
Line 117:            DropDownList quantityLister = (DropDownList)variantRepeater.FindControl("quantityLister");
Line 118:            string ddlvalue = quantityLister.SelectedValue;
Line 119:            int.TryParse(ddlvalue, out quantity);
Line 120:


Source File: c:\Inetpub\patios\chaircovers.aspx.cs    Line: 118

Stack Trace:

[NullReferenceException: Object reference not set to an instance of an object.]
   ChairCovers.productRepeater_ItemCommand(Object source, RepeaterCommandEventArgs e) in c:\Inetpub\patios\chaircovers.aspx.cs:118
   System.Web.UI.WebControls.Repeater.OnItemCommand(RepeaterCommandEventArgs e) +108
   System.Web.UI.WebControls.Repeater.OnBubbleEvent(Object sender, EventArgs e) +68
   System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +37
   System.Web.UI.WebControls.RepeaterItem.OnBubbleEvent(Object source, EventArgs e) +123
   System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +37
   System.Web.UI.WebControls.ImageButton.OnCommand(CommandEventArgs e) +111
   System.Web.UI.WebControls.ImageButton.RaisePostBackEvent(String eventArgument) +176
   System.Web.UI.WebControls.ImageButton.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +10
   System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13
   System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +36
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1565
2

There are 2 answers

0
Sarah Jean On BEST ANSWER

So I changed this:

DropDownList quantityLister = (DropDownList)variantRepeater.FindControl("quantityLister");

to this:

DropDownList quantityLister = variantRepeater.Controls[variantRepeater.Controls.Count - 1].FindControl("quantityLister") as DropDownList;

and it worked.

2
Charles Bretana On

It's been a while since I did this, but as an idea to try,

Since it's nested, the actual name of the nested header or footer control in the html, is a concatenation of the outer repeater control name, (I Think), an underscore ('_'), and the name of the inner header/footer control... Are you using this in your find?

Second suggestion: Change yr code

foreach (RepeaterItem item in variantRepeater.Items)
{
      decimal quantity = 0;        
      decimal.TryParse(((DropDownList)item.FindControl(
             "quantityLister")).SelectedValue, out quantity); 
      if (quantity > 0)
      {   
          string variantId = ((HiddenField)item.FindControl("variantId")).Value;
          orderForm.LineItems.Add(
                 new LineItem(catalogName, productId, variantId, quantity));
          basketUpdated = true; 
      }
}

And change it to:

foreach (RepeaterItem item in variantRepeater.Items)
{
      decimal quantity = 0;        
      decimal.TryParse(((DropDownList)item.FindControl(
             "quantityLister")).SelectedValue, out quantity); 
      if (quantity > 0)
      { 
          if (item == null)
              throw new ApplicationException(
                  "Can't locate RepeaterItem");
          object obj = item.FindControl("variantId");
          if (obj == null)
          {
              string sNL = Environment.NewLine;
              StringBuilder sb = new StringBuilder(
                     "Can't locate variantId HiddenField" + sNL +
                     "item Controls are:" + sNL); 
              foreach(Control ctrl in item.Controls)
                  sb.Append(ctrl.Name + sNL);

              throw new ApplicationException(sb.ToString());                
          }
          if (!(obj is HiddenField))
              throw new ApplicationException(
                  "variantId is not a HiddenField");
          HiddenField hfld = obj as HiddenField;

          string variantId = hfld.Value;
          orderForm.LineItems.Add( new LineItem(
                 catalogName, productId, variantId, quantity));
          basketUpdated = true; 
      }
}

Run it again and see what the error is...