Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Grid Live Refresh

3.24/5 (9 votes)
12 Jan 2008CPOL4 min read 1   588  
A classic scenario without a one-place answer anywhere on the web so far.

Scenario

Inside a ContentPlaceHolder (ContentPlaceHolder1) of a child web page, I place the following controls:

  • A GridView control (GridView1) to show data rows from the Categories table of the Northwind database.
  • An SqlDataSource (SqlDataSource1) to fetch the data from the database and bind them to the GridView.
  • A LinkButton (LinkButton1) to allow users to insert new data rows to the Categories table.
  • A Panel (Panel1) and a ModalPopupExtender (ModalPopupExtender1) control to provide the interface for inserting new data into the database table. The value of the PopupControlID property of the ModalPopupExtender is set to Panel1. This will cause the Panel1 panel to popup on the screen.
  • Finally, the GridView is wrapped inside an UpdatePanel (UpdatePanel1).

Each time a new data row is inserted into the database, we want to refresh the GridView data in a smooth, AJAX way without refreshing the whole web page. How can this be done? Read on to find out.

Solution

In order to add a new data row, the user clicks the LinkButton. Since the LinkButton is the value of the TargetControlID property of the ModalPopupExtender, clicking LinkButton1 effectively causes the Panel1 panel to popup on the screen.

Panel1 contains the appropriate data entry textboxes, the OK button (OkButton), and the Cancel button (CancelButton). Both these buttons are connected to the ModalPopupExtender through the OkControlID and the CancelControlID properties. Furthermore, the OnOkScript="onOkClick()" property declaration causes the execution of the onOkClick() JavaScript function when the user clicks the OkButton button.

The onOkClick() JavaScript function executes on the client side. It gathers user input and makes an asynchronous call to the DB.AddCategory web (and script) method of the DB web service. DB.AddCategory inserts a new data row into the database. Since this is an asynchronous call, success (onAddSuccess) and failure (onAddFailure) callback functions are defined, too.

Pay attention to the _doPostBack call of the onAddSuccess callback function. This is the code required in order to invoke a server postback of the OkButton control. Note, that since we are in a ContentPlaceHolder, the ID of the OkButton would be something like "ctl00ContentPlaceHolder01OkButton", and this is something that the JavaScript code must be aware of.

At this point, the server side code of the OkButton_Click method is executed. All it does it to cause the databound GridView to rebind itself to the SqlDataSource. Normally, this will cause the whole web page to refresh in the browser, which is undesirable. What we really want is to refresh the GridView without the page refresh effect. This is why I placed the GridView inside the UpdatePanel control.

The big question

The big question now is how we can cause the UpdatePanel to update as soon as the new data row has been inserted into the database. To cut a long story short, all we have to do is set the correct trigger. But, which control is it going to be?

And the big answer

If you think that the LinkButton should be the trigger, then you are like me, and unfortunately, you are wrong. The answer is that the OkButton control inside Panel1 must be the trigger to update the UpdatePanel. This is why we invoke a postback on OkButton as soon as the asynchronous Web Service call has finished. The postback causes the trigger to fire, and voila! The UpdatePanel along with the GridView are updated (the new data row appears as a grid row). Setting the trigger is quite easy:

XML
<Triggers>
    <ajax:AsyncPostBackTrigger ControlID="OkButton" EventName="Click" />
</Triggers>

Last but not least, make sure that you set the UpdateMode property of the UpdatePanel to "Conditional". Also, do not forget to make the DB Web Service available to the JavaScript code:

XML
<ajax:ScriptManager ID="ScriptManager1" runat="server">
    <Services>
        <ajax:ServiceReference Path="DB.asmx" />
    </Services>
</ajax:ScriptManager>

To recap, what you must keep in mind is the following series of events:

(1) The user clicks the LinkButton -> (2) The ModalPopupExtender pops up Panel1. The user enters data and clicks the OK button -> (3) The onOkClick() JavaScript code is executed. An asynchronous Web Service call is made, and a new data row is inserted into the database. Upon success, the control returns to the onAddSuccess callback function which -> (4) fires a postback to invoke the server side code of the OK button -> (5) Since the OK button is the trigger of the UpdatePanel, the postback effectively causes the UpdatePanel and its contents to update.

Points of interest

  1. MasterPages are everywhere. In this scenario, all controls are placed inside a ContentPlaceHolder of a child page. This alone brings the effect of modified control IDs. You must be careful if you want to invoke control postbacks from JavaScript client code.
  2. After having inserted a data row to the database, the databound GridView must be refreshed. Since the GridView is inside an UpdatePanel, this equals to updating the UpdatePanel. You can only achieve this by placing the appropriate trigger. In this scenario, this can prove to be unobvious at first.

Why I wrote this

It took me one week to solve this out. Googling the Internet only helped me with bits and pieces. It seemed like I couldn't find a straightforward and complete answer anywhere. That is why I decided to contribute this to the community. Asking is too easy, but providing solutions can be hard.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)