title: GridView rows jumping around while editing data
body: <p>I've got a simple intranet form (ASP.NET 2.0) with a GridView bound to data from Active Directory. It does this with an SqlDataSource that selects from a view that pulls the data from AD. This works better than doing LDAP queries directly from ASP.NET, since I can do table joins, etc. without much fuss. The GridView has a CommandField column with an edit button, and a few EditItemTemplates with DropDownLists for selecting valid values.</p>
  
  <p>Updates, on the other hand, <em>are</em> done by connecting directly to AD. To allow for this, I have to handle the OnRowUpdating event of the GridView, and set Cancel in the GridViewUpdateEventArgs to true, since the SqlDataSource has no update command defined. Then it just creates a DirectorySearcher, looks up the user based on distinguishedName (the data key of the GridView), calls GetDirectoryEntry() on the result, sets a couple properties, and finally calls CommitChanges() on the DirectoryEntry. No problems there - it's updating the data just fine.</p>
  
  <p>It <em>is</em>, however, behaving a little confusingly. It seems there's a bit of a propagation delay when updating the data. It takes roughly ten seconds after updating before the view used for the SqlDataSource reflects the change. I'm not sure if this is typical AD behavior, or if the view is connecting to a different DC than the one the update is being issued against. This behavior isn't a problem in and of itself, and I can live with it if necessary.</p>
  
  <p>But while that isn't a big problem, it's causing <em>another</em> issue - the GridView is sorted by default on the "company" column, which is one of the properties the user is allowed to edit. If the user changes the company on a row, waits a little while (or continues making multiple edits), then goes to edit another row, they could potentially end up editing a row adjacent to the one they wanted. This is because the GridView rebinds, and suddenly the row that had its company changed is sorted elsewhere in the list. The GridView is evidently triggering the edit based on the index of the row, and suddenly there's a different row at that index because the view used for the data source suddenly just caught up to reality.</p>
  
  <p>What's sort of perplexing is that the GridView is trying to data bind on every post-back. In the past, I've had to make sure to call DataBind() after making data edits to ensure the data is up-to-date, but now it's happily hitting the data source every time. And yet the page ViewState is coming in around 66 KB, so I know the GridView is putting its data there.</p>
  
  <p>So, off the top of my head, these would be a couple of fixes (that I haven't implemented successfully yet).</p>
  
  <ol>
  <li><p>Stop the GridView from data binding with every page load, and stick with what it's got cached in ViewState. There's no "Cancel" property on the GridView's OnDataBinding event args, and setting Cancel during the data source's OnSelecting event just leaves me with an empty GridView.</p></li>
  <li><p>Fix the propagation delay. Again, I don't have my heart set on that, but if it's a means of fixing the rows jumping around unexpectedly, then that's fine with me. Would I just have to make sure I'm explicitly connecting to the same DC both in the database view and when updating AD from ASP.NET? Or is there something more going on?</p></li>
  <li><p>Trigger the row edit based on the primary key of the row rather than the index. I'm guessing I'd have to create a CommandButton in the row, set the CommandArgument to the primary key of the row, then walk through all the rows in the GridView on post-back and manually set EditIndex accordingly.</p></li>
  </ol>
  
  <p>I'm open to other ideas too. If the ViewState ends up being a couple hundred KB, that's workable. This site is accessed over a pretty speedy LAN, and is strictly for internal use.</p>