Today I was working on a WebForm that includes a GridView which presents text boxes for various columns. I put these in the ItemTemplate so all of the rows could be edited at any time. The next requirement was to update certain read only columns (e.g. Total Amount) based on the changes of the others.
Originally, I had the entire GridView in an UpdatePanel, but that quickly proved to be a problem for two reasons. First, the updates were fairly slow. Second, the active control would lose focus after the partial postback. I briefly considered what I might do to "restore" the control focus, but decided to consider options other than the single UpdatePanel.
Another fleeting thought was to use an UpdatePanel for each control that could change or be affected by a change. That's a scary proposition. For my form, that would result in seven update panels per row!
While reading about the "dangers" of update panels, I came across a couple of posts about PageMethods. This appeared to be exactly what I needed. There would be no partial postback as required by the UpdatePanel. In fact, there would be no postback of any sort. The PageMethod would simply execute a WebMethod followed by provided success or failed callbacks.
A small amount of javascript and a couple of static methods on my webform later, and I was in business. The changing of data and tabbing through text boxes was lightning fast. And there was never any concern over losing control focus because none of the controls were re-rendered.
Here's a snippet of the javascript:
1 <script type="text/javascript">
2 function BaseAmount_Changed(ctrl, orderId, totalCtrl, changeCtrl) {
3 var text = ctrl.value;
4 var context = {};
5 context.totalCtrl = $get(totalCtrl);
6 context.changeCtrl = $get(changeCtrl);
7 PageMethods.BaseAmount_Changed(orderId, text, OnSucceeded, OnFailed, context);
8 }
9
10 OnSucceeded = function(result, userContext, methodName) {
11 var results = result.split(":");
12 if (results[0] == "true") {
13 userContext.totalCtrl.innerText = results[1];
14 userContext.changeCtrl.innerText = results[2];
15 }
16 }
17
18 OnFailed = function(error, userContext, methodName) {
19 alert('Change Failed: ' + error.get_message());
20 }
21 </script>
And the WebMethod declaration:
1 [WebMethod]
2 public static string BaseAmount_Changed( int orderId, string text )