As part of my preparation for Code Camp this weekend and the ATLAS talk I wanted to demonstrate how UpdatePanels in ATLAS are super easy to apply to existing application by showing off a really complex form in my West Wind Web Store and adding an several UpdatePanels to it to update some sections of the page.

 

As it turns out I was unable to make this work quite right, not because UpdatePanel didn’t work right – not exactly – but because my form is using a custom built Tab control. The page is here:

 

http://www.west-wind.com/webstoresandbox/admin/ShowInventoryItem.aspx?sku=WEBSTOREDOTNET&tab=Other

 

 

The page is multi-page layout that uses a custom written TabStrip control that uses JavaScript to switch pages which are contained in containers in ID tags below (so in designmode this page is one long page layout). This all works just fine in Postback mode because the page is repainting each time and script code gets injected when it posts back to ‘remember’ which page was active previously. What the code does on the server is use RegisterStartupScript() to set the initial page which is hardcoded. Unfortunately with an ATLAS UpdatePanelCallback that will fail, so although the panel will update the page properly, the tab display always wants come back on the first page as the page startup code doesn’t fire.

 

I even went as far as changing the generated startup code to read the page name dynamically from a hidden form variable (which does get properly updated by ATLAS BTW!), but that also doesn’t work – the startup code simply isn’t fired on a callback.

 

This means relying on startup code for any control changed inside an update panel is going to be a problem. I don’t think there’s a workaround for this particular problem either because UpdatePanels don’t allow you to fire a client side event on completion. This problem could be easily solved if there was a OnClientCompletiton handler on the UpdatePanel, but alas there isn't.

 

My original approach on that page was more to demonstrate that – in theory at least – update panels are very esay to deal with and I simply wrapped the main content into the panel. Besides the Tab control issue the rest of the page actually worked fine and properly updated the content. Of course it is bulky to do this and no less efficient than a full postback both in terms of content over the wire and the actual processing that occurs. But it does work a little smoother from a UI perspective.

 

A better approach though is what I did next: Only wrap UpdatePanels around smaller portions of the page. If you look at the page above, you can add SubItems and Related items on the SubItems tab. Those sections should be able able to be wrapped into an UpdatePanel and just work.

 

I did put that together but I ran into yet another snag – the Related Items Refresh works fine using the UpdatePanel wrapped around that section. However, the Remove operation fails to refresh the area properly. The list sits in a Repater object and using ItemCommand event to update the page.

 

<div class="gridheader">Related Items</div>

    <br />

    <atlas:UpdatePanel runat="server" ID="RelatedItemsUpdatePanel" Mode="Conditional">

        <ContentTemplate>

 

 

    <small>Related items are shown on the item display page as a sidebar. Related items can either be directly

    linked to other inventory items and their properties, or you can create custom text for the items.</small>

    <br />

    <br />

    <asp:Repeater runat="server" ID="repUpsellItems" OnItemCommand="repUpsellItems_ItemCommand">

    <HeaderTemplate><table cellpadding="3" style="width:500px;margin-left:20px;"></HeaderTemplate>

    <ItemTemplate>

    <tr>

        <td><li><asp:HyperLink runat="server" NavigateUrl='<%# this.LookupRelatedItemExpression(Item.Entity.Sku,Eval("Sku") as string ) %>'

         Text='<%# Eval("Descript") %>' /></li></td>

        <td style="padding-left:20px;"><asp:LinkButton runat="server" CommandArgument='<%# Eval("UpsellPk") %>'  CommandName="Remove" Text="Remove"></asp:LinkButton> </td>

    </tr>

    </ItemTemplate>

    <FooterTemplate></table></FooterTemplate>

    </asp:Repeater>

    <hr />

    <a class="imagelink" href="javascript:OpenRelatedItem('<%= Item.Entity.Sku %>');" >

    <asp:Image runat="server" border="0" ID="imgNewRelated" ImageUrl="~/images/NewDocument.gif" /> Add related item</a> |

    <asp:LinkButton ID="btnRefreshRelated" runat="server" Text="Refresh" class="imagelink"/>

    </ContentTemplate>

    </atlas:UpdatePanel>

 

 It removes the item, then reloads the list data and rebinds the list with code like this:

 

protected void repUpsellItems_ItemCommand(object source, RepeaterCommandEventArgs e)

{

    if (e.CommandName == "Remove")

    {

        int UpsellPk = 0;

        int.TryParse(e.CommandArgument as string, out UpsellPk);

        if (UpsellPk == 0)

            return;

 

        if (this.Item.RemoveUpsellItem(UpsellPk))

        {

            this.ErrorDisplay.ShowMessage("Related item removed.");

            this.BindUpsellItems();

        }

        else

            this.ErrorDisplay.ShowError("Failed to remove related item: " + Item.ErrorMessage);

    }

}

 

BindUpsellItems goes out and reloads the list and then DataBinds() the list again with the new udpdated data so in effect DataBinding on this control occurs twice. I suspect that’s what the problem is but in any case the removed item continues to show on the page. What’s really odd about this is that there’s also a Refresh button inside of the panel and that works just fine. It’s only the above code that’s rebinding that appears to be failing. I wonder if ATLAS is somehow picking up the data

 

There’s also a major Designer issue on this form: Visual Studio crashes whenever the page with the UpdatePanel is opened in the Visual Designer. The page is pretty complex as you can see, but it loads just fine without the UpdatePanel on it. Put the UpdatePanel on it and it fully crashes VS every time.

 

All of this is not very encouraging and doesn’t exactly want to make me jump out and use ATLAS for production code… yet at least. <s>