0

Upgrading from the AjaxControlToolkit Collapsible Panel using jQuery in Asp.Net WebForms: Remembering the Panel State across postbacks.

by Jon 7. April 2011 22:11

In 06?/07 the AjaxControlToolkit was the Jewel in the Crown in the Microsoft Web Development Platform , an easy way to do Ajax for Asp.Net Web Forms.  It was really easy rapid development, tightly integrated into Visual Studio and it was Open Source, it was new and cool and quick to use.  Things changed, the cool kids moved onto other things, and people discovered that although it had its advantages the AjaxControlToolkit to wasted lots of bandwidth, constricted you to a particular look and feel, and had the potential to introduce bugs you couldn’t fix.  The current state of play is the toolkit hasn’t seen a new release since September 2009, and frameworks and browsers progressed massively.

There are lot of sites and systems that still use ASP.Net WebForms and many of them use the AjaxControlTookit to fill UI gaps.  We still use this toolkit in our day job system and I decided that we need to swap out the functionality the toolkit provides to jQuery.  The two controls I needed to replace were the Collapsible Panel and the Accordion.  There were examples online on doing both but I couldn’t find any examples that persisted postback.  I needed a collapsible panel that I can expand and contract with AJAX/JQuery but when the user presses a button that posts back to the server I want the server to return the page in the same state before the postback, i.e. still expanded, or still collapsed.  I also need jQuery/a Pattern that can easily be swapped out and to keep the UI experience consistent so I can update multiple pages and controls in one refactor sweep.

Surviving Postback: Collapsible Panel , using jQuery

The following snippet of code is a drop in replacement for the AjaxControlToolkit Collapsible Panel, it has been written to be a simple replacement for he AJAX extender but using jQuery and a small amount of code behind to return the panel in the correct state on postback.  This is what you need to do if you want to create the sample in Asp.Net Webforms from scratch on a separate page but it is even easier to replace and customise all your collapsible panels in your existing application.

Include jQuery in your Page Header

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js" type="text/javascript"></script>
 

Add a Hidden Field to your Page/Control to store the Expanded State

<asp:HiddenField ID="ExpandState" runat="server" />

There is a Panel that shows some header information

<asp:Panel ID="Panel_Title" runat="server" Height="15px">
    <asp:Label ID="Label_Expander" runat="server" style="float: left" Text="Edit (Show...)" />
    <asp:Image ID="Image_Expander" runat="server" ImageUrl="/images/dn.gif" style="float: right" />
</asp:Panel>

 

There is a Panel that shows some content

<asp:Panel ID="Panel_Content" runat="server" style="overflow:hidden">
    This is some Content
</asp:Panel>
 

Add some jQuery to Expand and Contract the Content Panel when a user clicks on the Title Panel

<script type="text/javascript">
    $(document).ready(function () {

        // When a user clicks on the Title Panel
        $("#<%= Panel_Title.ClientID%>").click(function () {

            // Toggle the Panel_Content Visibility
            $("#<%= Panel_Content.ClientID%>").slideToggle(300, function () {

                // When the Content Panel has completed its animation check to see if the Content Panel is visible
                if ($("#<%= Panel_Content.ClientID%>").is(":visible")) {

                    // Set the HiddenValue Expanded State to 'Expanded' and Update the UI
                    $("#<%= ExpandState.ClientID %>").val("Expanded");
                    $("#<%= Label_Expander.ClientID %>").html("Edit (Hide...)");
                    $("#<%= Image_Expander.ClientID %>").attr("src", "/images/up.gif");

                } else {

                    // Reset the Hidden Value and reset UI back to its original State
                    $("#<%= ExpandState.ClientID %>").val("");
                    $("#<%= Label_Expander.ClientID %>").html("Edit (Show...)");
                    $("#<%= Image_Expander.ClientID %>").attr("src", "/images/dn.gif");

                }

            });

        });

    });
</script>

 

In your code behind add this code in the page/control load:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    ' Serverside Expander Code
    If Me.ExpandState.Value = "Expanded" Then
        Label_Expander.Text = "Edit (Hide...)"
        Image_Expander.ImageUrl = "/images/up.gif"
        Panel_Content.Style.Clear()
    Else
        Label_Expander.Text = "Edit (Show...)"
        Image_Expander.ImageUrl = "/images/dn.gif"
        Panel_Content.Style.Add("display", "none")
    End If
End Sub
 

Surviving Postback: AjaxControlToolkit Accordion, using jQuery

The following snippet of code is a drop in replacement for the AjaxControlToolkit Accordion, you can simply replace the AJAX extender with the jQuery and add a small amount of code behind always show the correct panel on postback.  This accordion only shows one panel at a time. This is what you need to do if you want to create the sample in Asp.Net Webforms from scratch but it was written so it is really simple to swap out your old Accordions.

Include jQuery in your Page Header

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js" type="text/javascript"></script>

 

Add a Hidden Field to your Page/Control to store the clientid of the currently Expanded Panel.  The value of this hidden field is “” when there is no expanded panel

<asp:HiddenField ID="ExpandedClientID" runat="server" />

 

Any Number of Title and Content Panels

<asp:Panel class="TitlePanel" ID="Panel_Title1" runat="server" Height="15px">
    <asp:Label ID="Label_Expander1" runat="server" style="float: left" Text="Title 1" />
</asp:Panel>
<asp:Panel runat="server" ID="Panel_Content1" class="ContentPanel">
    Content 1
</asp:Panel>
<asp:Panel class="TitlePanel" ID="Panel_Title2" runat="server" Height="15px">
    <asp:Label ID="Label_Expander2" runat="server" style="float: left" Text="Title 2" />
</asp:Panel>
<asp:Panel runat="server" ID="Panel_Content2" class="ContentPanel">
    Content 2
</asp:Panel>

 

Add the following jQuery code

<script type="text/javascript">
    $(document).ready(function () {

        //toggle the component with class ContentPanel when the corresponding Title is clicked
        $(".TitlePanel").click(function () {

            // The Content Panel we want to manipulate is the Next One after this
            var ThisNextContentPanel = $(this).next(".ContentPanel");

            // Toggle This Content Panel
            ThisNextContentPanel.slideToggle(300, function () {

                // and then Hide the Other Content Panels
                $(".ContentPanel").not(ThisNextContentPanel).hide(200);

                // Set the Selected Panel to the Hidden Variable
                $("#<%= ExpandedClientID.ClientID %>").val(ThisNextContentPanel.attr('id'));

            });

        });

    });
</script>

 

Add the follow code behind to make sure we only display the correct panel on each postback:

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    ' Show/Hide Panel_Content1
    If Panel_Content1.ClientID = ExpandedClientID.Value Then
        Panel_Content1.Style.Clear()
    Else
        Panel_Content1.Style.Add("display", "none")
    End If

    ' Show/Hide Panel_Content2
    If Panel_Content2.ClientID = ExpandedClientID.Value Then
        Panel_Content2.Style.Clear()
    Else
        Panel_Content2.Style.Add("display", "none")
    End If
End Sub

 

And that's it, we are now several steps closer to dropping the AjaxControlToolkit from our code base Smile

Tags: , , , ,

AjaxControlToolkit | vs2010 | jQuery

0

Deploying Asp.Net to a different time zone, Temporal Future Shock! Specified argument was out of the range of valid values. Parameter name: utcDate

by Jon 17. December 2010 09:57

You would have never of thought it but if you compile ASP.NET in a different timezone you could cause yourself some temporal problems.  I recently discovered that parts of ASP.NET are date specific and if you compile an ASP.NET application in one timezone (The UK), and deploy to another timezone (California) you may find that your web application won’t work correctly until the time catches up.  Its all to do with the date stamp in the assemblies, when you install your application onto a server in california the timestamps on the assembly files may be in the future and parts of the ASP.NET framework will refuse to load them.  Just by waiting 8 hours for time to catch up the problem will resolve itself!  Its defiantly worth saying this doesn’t effect all server setups I had no problems with a customer running server 2008 in a different timezone, I only came across this problem with an AJAX enabled system when a customer was running server 2003, but I haven’t had time to test different scenarios

I installed the application the AJAX was ‘working’ however nothing was styling correctly

I viewed the source of the page and started debugging by copying the WebResource.xsd url into different tab, I was surprised to see the following error:

Server Error in '/' Application.

Specified argument was out of the range of valid values.
Parameter name: utcDate

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.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: utcDate
Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

I returned to the system after 8 hours and the site was working and the error was gone! Be careful out there, this was a fully patched server 2003!

Tags: , , , , , , ,

asp.net | Deploy | development | General | IIS | Maintanance | TechSupport | vs2010

1

Developer Developer Developer South West #DDDSW

by Jon 6. June 2010 22:32

DDD SouthWest 2

I trundled down to DDDSW yesterday for a fantastic day of DDD geekyness.  The DDDSW team had thoughtfully laid on a Getting Started with .Net track I thought it would be a great way for my brother in law Kevin who is currently leaning dotnet to pick up some more skills.  Although the day was fantastic, I wasn't prepared enough, I need to remember to get alot more sleep before DDD events, as a consequence combined with the heat I wasn't in right frame of mind to mingle and chat as much as usual but I did talk to a bloke from Lincolnshire called Rob.

My Favourite Design Patterns, Gary Short

Yeah that was me, I was the demonstration!  No one else wanted to put there hand up, so a very tired jon went up and got my lefts and rights confused for a second.  Gary was explaining design patterns and how design patterns are used to facilitate leaning, they are a way of teaching people how to do stuff in a repeatable way without having to know the details of how the pattern works.  It was a great session.  I now know that my singleton pattern isn't as efficient as it should be, the singletons have written in the past have a couple of locks in them but I think I can bypass it with a static readonly:

class Singleton
{
    Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            return Nested.instance;
        }
    }
    
    class Nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static Nested()
        {
        }

        internal static readonly Singleton instance = new Singleton();
    }
}

What was nice about this session was that I kept on recognising patterns in my own code without knowing some of the official names of the patterns. I am using Garys design patterns without realising it because it seemed like the best thing to do at the time.

So you want to try scrum, Nathan Gloyn

Due to the number of true geeks at dddsw 2, this turned out to be a smallish session.  The way people develop and interact and the psychology of software development interests me.  In the past Agile, scum and other modern methodologies have been sold as something that can be achieved with a specific piece of software (which the person is trying to sell to you) or sold as something that needs to be done in one go (which the person can help you with through consultancy).  I disagree with this and I was very happy to see Nathan taking the same approach.  This was a very un-technical presentation of the building blocks of scrum, and given in a way that said you can get there in little steps.  I believe people get there quicker if they take small steps rather than a big bang change.

Scrum Board

Crap Code and the Disasters it Causes, Phil Winstanley

You have seen it before, every developer has seen it.  You join a project, you pick up some old code, or perhaps your working with someone, or perhaps it is you!  The code is scary, Phil went through some of the crap code he has seen in his travels and categorised the code into separate developer personality types.  Some of the code was very scary, some of the code was familiar and I may have even written some of it!  I understand the problems faced by developers that have progressed from vb within a single company, the world is a very different place.  In the past you sometimes had to fudge things to get them to work and habits die hard.  When your this kind of developer and your working on monolith of a project that was originally ported from 20 years old VB1 code there is fear to change things due to extreme spaghetti code.  When you have really old nasty missions critical code you learn from your peers not to change it too much.  I remember fixing some really code and a random appearing 6 months later for no valid reason.  Crap code is bad, but sometimes code is beyond repair, and attempting to fix it will also causes disaster.

Ajax with JQuery, George Adamson

George Adamson wrote some of JQuery so if you want to learn about AJAX with JQuery go see George.  A Great session it was a bit of a light bulb moment to see how query works in anger, AJAX is dead long live AJAX.  Microsoft has shifted AJAX development to JQuery so you really need to start using JQuery instead.  I'm not sure where this leave some of the control libraries such as Telerik?JQuery

Clean User Interfaces with ASP.NET Webforms, Dave Sussman

MVC is ok but it is relatively new technology, WebForms is tried and tested but know to generate messy html.  However was keen to show us if you turn everything off, turn the view state off, don't run with the .NET default settings and use dotnet 4 if you can and you get nice clean html.  WebForms isn't going to go away as it works, there are lots of sites and applications out there in the wild and there are other things in the pipeline for webforms such as MVP, that will only extend its life.DDD End, oh and the sponsers

All in all I had a fantastic day at DDDSW, a real credit to the organisers and I am already looking forwards to the next event.

Powered by BlogEngine.NET 2.0.0.36
Original Design by Laptop Geek, Adapted by onesoft, and finally some tiny tweaks by JonAlb