Something that has always bothered me about using “light boxes” or even popup windows and data is added or updated in that light box the parent window that is displaying the data doesn’t refresh the data without refreshing the page. Using AJAX to improve the user experience makes matters worse because the data should automatically asp.net refresh when changed. This tutorial will show how to update a GridView on a parent page when a light box updates the data. I will be using Fancybox but the same functionality can be added to any kind of light box.
The Data Page
For simplicity I’ll be using trusty old AdventureWorks. To cut down on the fields my GridView will display, I’m going to create class called LightContact. Here’s the class:
[crayon-5bca5c2906615784767864/] I totally stole this idea from a recent Silverlight video I was watching. I would give the author credit but I completely forgot which one it was. Sorry! Basically the point of this is to simply cut down on the amount of data that will display in the asp.net refresh GridView.
I created an Entity Data Model that defines the Contact table from AdventureWorks. The data method or model you choose really doesn’t matter. I really like the Entity Framework so that’s what I’m sticking with.
[crayon-5bca5c2906629058917984/] If you’re not familiar with what’s going on here, I’m simply selecting 30 contacts and creating a collection of the LightContact class that was created above. Then it binds that collection to grdContacts.
Add/Update Contact Page
Now let’s say I want to add a new contact. I don’t want to re-direct to a new page, I’d like a “light box” to overlay the current page to handle the new entry. There are a couple of ways to go about this. My preferred method is to add a separate add/update page that will open inside an iframe within the fancybox. The other option would be to add the add/update form to the same form inside of a hidden panel. If you are going to do this and are using Fancybox, you’ll need to make a small tweak. I’ve described the process in this post. But again, I prefer to add a new page to handle this. I created a page named ContactAddUpdate.aspx. I’ll not include the code here but it basically pulls in a contact’s information if the id is passed in the querystring otherwise it assumes a new contact will be created.
Implement the Fancybox
Using Fancybox is quite simple. You add a reference to the fancybox.js file (it’s name something like jquery.fancybox-1.3.4.pack.js, make sure you use the packed version for production). I would also recommend adding the easing and mousewheel packs as well. You also need to reference the fancybox.css file as well.
If you’re using a MasterPage it would be a good idea to include the jquery script on your MasterPage, that way any page that uses it will automatically have the script ready to use. If you’re not using a MasterPage then add the following to your page. I like to add it at the bottom of the page just before the ending </body> tag. If you prefer to put it in the <head> then that is fine too. It’s up to you.
Update the Web Form
Above my Gridview I’m going to add a Hyperlink and set its CssClass to “fancybox”. Also, because I want to open a different page into the lightbox I am also going to add “iframe” to the class, here’s the HTML:
[crayon-5bca5c2906633213776329/] Now when I view the page in a browser and click the Add Contact link, a fancybox will appear with my Add/Update contact page loaded in an iFrame.
Now to refresh the parent
It doesn’t make much sense to open a fancybox and do some action, especially when dealing with data on the opening page, and just close the fancybox. The parent page should be automatically updated when the light box closes. The easiest way to accomplish this would be to add a window.location.reload(true); when on the close event of the fancybox. So the JavasScript would look like:
[crayon-5bca5c2906637053830216/] Now when the fancybox closes the parent window will reload and the change in the data will be displayed.
But what’s the point of using a lightbox and having to refresh the entire page when it closes, that kind of defeats the purpose of why we’re opening a light box in the first place. Light boxes are supposed to enhance the user experience and eliminate all the unnecessary post-backs to the server. I want to just reload the GridView without having to reload the entire page and cause that annoying flicker on the screen.
Enter the UpdatePanel
So how do we only refresh the GridView? First, we add a Button or LinkButton inside the UpdatePanel like so:
[crayon-5bca5c290663b866703543/] Then in the code-behind I’ll add an onclick event. All this method will do is call the bindContacts method we created earlier. We also need to call the Update method for the UpdatePanel since its UpdateMode=”Conditional”.
[crayon-5bca5c290663e602318034/] Since the LinkButton is inside the UpdatePanel an AsyncPostBack will occur, so only what’s in the UpdatePanel will change. The page will not refresh.
You’re probably thinking, “This doesn’t solve anything.” You would be correct. We still have to somehow trigger the LinkButton when the fancybox closes.
[crayon-5bca5c2906643594087673/] Here’s the new HTML:
In the onFancyClose function Remove the window.location.reload(true) with the following:
If you’ll notice the id of the LinkButton actually ends up being MainContent_lbRefresh because my page is in a MasterPage and so everything on this page has the prefix of the ContentPlaceHolder ClientID which happens to be MainContent. The problem is that the argument sent to the __doPostBack method is not the ID of the control or even the ControlID but it’s a little different.
So basically I wrote the regular expression to extract both parameter values from the linkbutton. Then I manually call __doPostBack with those two extracted parameters. It may not look pretty…but it works!
Now when you view the page in the browser, add or update a contact and close the fancybox and only the data should refresh.
What about using a different light box alternative?
The concept would be exactly the same for any other light box alternative or even just opening a popup or modal display. First look to see if the method you are using as an fancybox onClose event and pass the same onFancyClose function. If you’re using a popup you can add an event to the window.onbeforeunload function and have it run parent.onFancyClose();.