views:

1111

answers:

4

I developed a user control that displays a list of products and it works pretty good. Then I dropped this user control into another user control that allows the user to pick different criteria and the product UC updates to show those products, all pretty slick and with AJAX via UpdatePanel.

All was working just fine... then another requirement came in. The "search" control needs to be separate from the product control (so they can be positioned separately). Initially, I thought this was no problem as I would give the search control a reference to the product control and then it would talk to it via reference instead of directly inside the control (which has been removed).

And they do talk. But the product control loads, but refuses to display.

I checked and it is being passed via reference and not a copy ( as best I can tell ).

There is an updatepanel in the search control. There is an update panel in the product control. And then for good measure, there is an update panel surrounding them both in the actual search aspx page.

I've tried setting the product control update panel to conditional and then fire the .Update() method manually.

What's the secret here?

TIA!

SOLVED

Thanks to Jamie Ide for the tip to use events.

Search Control and Product control still have internal update panels, and NO LONGER have them on this particular page.

Search Control now raises an event OnSearchResultsUpdated and exposes the found items in properties. The page subscribes to this event and takes the properties and passes them to the product control and triggers triggers a .Refresh() method on the product control which simply calls the .Update() on its internal updatepanel.

The Product control, FYI, accepts products in several different flavors. A list of distinct SKUs, a list of product ids, a named collection in our database and finally a given product category.

Our designers need to be able to create a new page, drop the control onto it and set some properties and voila! New site page. They don't want to require a programmer's involvement. So keeping the controls self contained is a requirement. Fortunately all the changes I made still work completely with the other uses of the product control.

THANKS AGAIN SO MUCH!

+2  A: 

I don't think there's really enough information to work with here, but my best guess is that the Product control is not getting data bound. You may try calling myProdcutsCtrl.DataBind() from the search control (or something inside the Product control that cause a DataBind() for instance myProductCtrl.Search(value1, value2, value3).

One other thing you might try is removing the UpdatePanels and seeing if things work. Then add them back in once you get core functionality going.

UPDATE: I've gone ahead and put some example code that works here which I believe accomplishes what you want. What follows are snippets for the sake of saving space, but include all code necessary to make it run. Hopefully this will at least give you something for reference.

Things to try:

  1. EnablePartialRendering="true|false" setting it to false will force the natural postbacks and is good for debugging UpdatePanel problems.
  2. Make sure you are seeing Loading... come up on your screen. (maybe too fast depending on your dev computer)

Page.aspx

<%@ Register Src="~/Product.ascx" TagPrefix="uc" TagName="Product" %>
<%@ Register Src="~/Search.ascx" TagPrefix="uc" TagName="Search" %>

...

<asp:ScriptManager runat="server" ID="sm" EnablePartialRendering="true" />
Loaded <asp:Label ID="Label1" runat="server"><%= DateTime.Now %></asp:Label>

<asp:UpdateProgress runat="server" ID="progress" DynamicLayout="true">
<ProgressTemplate><b>Loading...</b></ProgressTemplate>
</asp:UpdateProgress>

<uc:Search runat="server" ID="search" ProdcutControlId="product" />
<uc:Product runat="server" ID="product" />

Search.ascx

<asp:UpdatePanel runat="server" ID="searchUpdate" UpdateMode="Conditional" ChildrenAsTriggers="true">
<ContentTemplate>
<p>
 <asp:Label runat="server" AssociatedControlID="filter">Less than</asp:Label>
 <asp:TextBox runat="server" ID="filter" MaxLength="3" />
 <asp:Button runat="server" ID="search" Text="Search" OnClick="SearchClick" />
</p>
</ContentTemplate>
</asp:UpdatePanel>

Search.ascx.cs

 public string ProdcutControlId { get; set; }
 protected void SearchClick(object sender, EventArgs e)
 {
  Product c = this.NamingContainer.FindControl(ProdcutControlId) as Product;
  if (c != null)
  {
   c.Search(filter.Text);
  }

 }

Product.ascx

<asp:UpdatePanel runat="server" ID="productUpdate" UpdateMode="Conditional" ChildrenAsTriggers="false">
<ContentTemplate>
<asp:Label runat="server">Request at <%= DateTime.Now %></asp:Label>
<asp:ListView runat="server" ID="product">
<LayoutTemplate>
 <ul>
  <li id="itemPlaceHolder" runat="server" />
 </ul></LayoutTemplate>
<ItemTemplate>
 <li><%# Container.DataItem %></li></ItemTemplate>
</asp:ListView>

</ContentTemplate>
</asp:UpdatePanel>

Product.ascx.cs

IEnumerable<int> values = Enumerable.Range(0, 25);
public void Search(string val)
{
 int limit;
 if (int.TryParse(val, out limit))
  product.DataSource = values.Where(i => i < limit);
 else
  product.DataSource = values;
 product.DataBind();
 productUpdate.Update();
}

Code does NOT represent best practices, just a simple example!

Josh
Hmm... I thought it was pretty clear without code, but I guess not. The only thing NOT happening is the display is not being updated. I've stepped through the code and all the data is getting loaded just fine.
peiklk
Well you described the problem perfectly, it's just sometimes the devils in the details! And in this case the details may well be the code. .NET is fickle beast and timing is everything!
Josh
+1  A: 

If I understand you right you have a layout like this:

Outer UpdatePanel
  SearchControl
    Search UpdatePanel
  ProductControl
    Product UpdatePanel
      Databound Control

Which one of those update panels is actually being called?

I assume that if you check the network traffic with something like Fiddler or Firebug if you're using Firefox, you aren't seeing any HTML for the product update panel coming back?

Have you tried doing something like:

UpdatePanel productUpdate = 
              Page.FindControl("Product UpdatePanel") as UpdatePanel;

if (null != productUpdate){
  productUpdate.Update();
}
Zhaph - Ben Duguid
+1  A: 

By default, if a postback is made from an UpdatePanel, only that control will be updated/re-rendered (this is called partial page-rendering).

To also update/re-render other UpdatePanels, you have to either:

  • set their UpdateMode property to Always
  • add the control that makes the postback to their Triggers collection

Check this page in MSDN for details.

M4N
+1  A: 

I'm fairly new to AJAX, but I don't think it's a good idea for user controls to have UpdatePanels. I would also advise you not to have the user controls reference each other; they should communicate through events and methods controlled by their container.

I do something similar with two user controls for a master-details display. The master raises an event when an item is selected from a list, the containing page handles the event and calls a method on the details display to display the selected item. If I remember correctly, my first attempt had UpdatePanels in the user controls and I wasn't able to make that work. Having the user controls inside an UpdatePanel on the page works fine.

Jamie Ide
I'll explain more tomorrow at the office, but there is a requirement for the control to be self-policing on this front. The product control is a multi-purpose control used in several places and the web designers need to be able to just plug and play.
peiklk
Doing this with the events helped and "separated" the concerns of the controls. The search control exists to return a list of products. The product control exists to display a list of products. The containing page tells the product control what products to display in every other case, so here it just gets that list from the search control.I had to keep the update panel in each control, but also wrapped them on the containing page too. THANKS!
peiklk