/dev/null [tony lombardo]

Anything and everything ASP.NET and more. Expect to see tips and tricks, opinions on new technology, and fun code samples, along with the occasional rant.
Demystifying Infragistics WebGrid DataBinding

Think you know everything about how the grid databinds?  Just starting to work with the grid and want to understand databinding?  Either way, read on.

DataBinding First Steps

In the basic scenario, you set the DataSourceID of the WebGrid at design-time, and your done.  Well, almost done.  There are a couple of additional properties that will be critical in making the grid's internals like sorting and paging work.  First, be sure to set the DataKeyField on the grid to the primary key field of your database table.  Next, I like to set the Band's BaseTableName property as well, don't actually know if this is necessary, but it's there so I set it.  This creates a link between a given band, and a Table in the datasource, which sounds like a good thing to me.  These properties can all be set at design-time or run-time.  Speaking of run-time..

DataBinding in Code

The first step - use the InitializeDataSource event of the grid!  Because the grid requires data at different points during the page lifecycle according to the features being used, there isn't one place where data can be bound.  Assigning data in the page_init may be too early in some cases, and page_load may be late in other cases.  Because of the strict requirements the grid has on when it needs data, the InitializeDataSource event is how the Grid will request data.  In this event, you must assign the grid's datasource (and be sure if it's a dataset, it has data in it).  You don't need to call DataBind, just setting the datasource is enough in this event.

And now for an apology....  If you used the WebGrid between 2006 and 2008, you likely noticed that the InitializeDataSource event had 'disappeared' from the CLR2.0 grid (in C# only).  At first this seemed like a good idea.. the datasources included in VisualStudio 2005 didn't require manually calling DataBind anymore, so the event wasn't needed, right?  Wrong!  I forgot about the key scenario of run-time databinding.  I gave the go-ahead to hide the event (we didn't remove it from the object model, we simply made it 'invisible').  We realize the oversight and finally took action to make the event public again.  Thank you to all of the customers who called us out on this and plead to get the event back.  If you go into Visual Studio 2005 or 2008 and notice that "InitializeDataSource" is missing form the Grid's event list, you can manually add the event handler.  This can be done declaratively through the WebGrid's ASPX (OnInitializeDataSource="myhandler") or through code in the OnInit method.  (grid.InitializeDataSource+=...)

[Note: A special thanks to Chris Lukose, the Infragistics Corporate Trainer for his work in lobbying for this event to be brought back again.]

2 Way DataBinding (Automatic Updating)

Did you know that the grid supports automatic data updating through the datasource control?  The days of complicated event handlers dealing with DataSets accepting and rejecting changes are over!!  Let's take a SqlDataSource for an example of how to use this feature. 

When you create the datasource be sure to click on the "advanced" when building the select statement.  You'll see a checkbox for "generate insert, update and delete".  Checking that box will enable the datasource to perform all of the 'crud' operations on your table.  The grid will automatically update the data, but first a 'postback' must occur.  I put a postback in quotes because it can be the traditional full page, or it can be an asynchronous AJAX style postback.  If you want the database to be updated with each row modification, you can add a server-side "RowUpdate" event handler.  Enabling the AJAX functionality of the grid (click the "Enable AJAX" checkbox in the smart tag at design-time, or set grid.DisplayLayout.LoadOnDemand=Xml) will make the updaterow happen asynchronously, making the entire update process transparent to the end user.  If you can't get updating working, check to be sure you set the grid's DataKeyField and BaseTableName properties (Yes, I'm speaking from experience).

UpdateRow VS UpdateRowBatch

When you take a look at the events for the Grid, you'll notice a few "Update" and "UpdateBatch" events.  What's the difference?  The Update events will fire as soon as the action occurs.  For instance, "UpdateRow" fires when you modify a value in a row and then focus leaves that row.  UpdateRowBatch however, will not fire until some mechanism cases the page to be posted back to the server (again, this can be a traditional or AJAX postback).  Using UpdateRowBatch means you can have a button which is used to update all changes once the user is done.  This is a very common usage scenario where the end user may be modifying multiple fields, but doesn't want to commit changes until they're sure it's right.  There is one oversight though.  The current implementation of UpdateRowBatch will fire the update events as soon as any postback occurs.  This could have been the result of any button click, or any other control.  This unfortunately means that you must commit the changes to something, even if the 'save' button was not clicked.  You can work around this by ensuring that nothing else will cause the page (or the grid) to postback in your application other than the 'save' button, but I'm sure there are going to be cases where that's not possible.  This is something that I'm currently lobbying to change in the Aikido version of the grid.

Manual Updating (Disconnected Data)

If the datasource you're using doesn't support automatic updates (business objects, datasets, lists) then you'll need to take the changes from the grid and persist them into your datamodel.  The easiest approach is to again use the UpdateRow or UpdateRowBatch events which will fire for each updated row, giving you an opportunity to persist the changes.  You can use the eventargs to find out the old values and new values, and decide to accept or reject the changes.  When manually updating your database, I'd recommend keeping your data in a keyed collection to make it easy to get a 'row' using a key value (primary key filed).  As an example, if you're binding to a collection of 'people', be sure that your collection is keyed on "personId".  You can make "personId" a hidden column in the grid, so that it doesn't show up in the display for the end user.  Additionally, if you make it hidden, be sure to make it 'serveronly' so that the data for that column never even has to be transmitted over the wire (why waste the bandwidth when you only need the data on the server..)

Advanced DataBinding

If you thought you knew everything about databinding in the grid, here's a hidden gem.  The EventArgs passed into the InitializeDataSource event can be upcast to "DataSourceEventArgs".  What does that mean?  It gives you fine grained functionality of how the grid retrieves data.  You can use this to implement partial databinding in the grid (feed the grid ONLY the rows needed for the current page, etc).  This is critical for achieving optimal performance in your application, since only you really know the details of your data implementation (Are you caching your data?  Is it quicker to retrieve all of the data at once and store it in a cache, or does it make more sense to fetch 'pages' of data at a time? ...)  As this is the case, you can use the InitializeDataSource event and the DataSourceEventArgs to feed the grid to match your data model.

Posted: 29 Jan 2008, 15:43
Filed under: ,

Comments

George Fahnbulleh said:

Tony the grid as a single level grid functions beautifully.

What I believe is missing is a data control, like you have on the Win side that handles hierachical data.

On the other hand, a very good sample project of multi-level grid where rows are added with a database auto-generated key, would be splendid.

Quite frankly I am of the opinion that the product should ship with that because it is the No1 issue for developers using the grid!

# January 29, 2008 7:51 PM

Tony Lombardo said:

George - Sounds like you've been reading our product plans :)  

We're actually about to ship a new CTP for our "Aikido" controls and included is a HierarchicalDataSourceControl.  The control is still really new, and the WebGrid doesn't understand how to bind to it yet, but the plan is for the two to work together.  In the meantime, I'll see if I can put together a post on hierarchical databinding.  

Thanks for the feedback!

# January 30, 2008 10:20 AM

Peder Strauss said:

Hi Tony

I REALLY agree with George.

Hierarchical grid is one of my most urgent issues with WebGrid. I have got i working but it is SLOW. So I am looking forward to a sample from you or a new HierarchicalDataSourceControl.

Regards Peder

# April 8, 2008 3:17 AM

Ian Murphy said:

Tony,

The pager control on the webgrid is ok but if you want to add any extra functionality such as a search box or links per quarter with a drop down to 'page' the data out in 15 row chunks then you are obliged to write your own pager control. Up to there is fine.

If you then want to get the grid to update using ajax it is highly difficult since there isn't any way of firing the page click event from the client side, nor is there any way of passing in customised page information, so you cannot tell the grid to fill itself with, say, 2007-Q3-P2 of data containing the word 'Florida'.

Ian

# April 14, 2008 10:15 AM

Paul Newell said:

Hi Tony, thanks for the info.

The updates are working very nicely. One issue I have though is I am working with an Ultrawebgrid set to OutlookGroupBy, each time I update a field the data changes, which is great, but the grid collapses all the expanded groups, I cannot find a way around it. Any ideas ?

Kind Regards

# April 16, 2008 7:54 PM

Tony Lombardo said:

@Paul - The grid should retain the expanded status unless you're rebinding.  Check and be sure you're not re-assigning the datasource or manually calling DataBind on the grid when you don't need to.  If you're using a DataSourceControl and assigning the grid's DataSourceID, you never have to call databind from code, and you don't even have to set the DataSource (other than at design-time)

@Ian - The grid actually does have a method which will load pages of data asynchronously - oGrid.goToPage(page) http://help.infragistics.com/Help/NetAdvantage/NET/2008.1/CLR2.0/html/WebGrid_Object_CSOM.html

Does that suit your needs, or do you need something more?

@Peder - When ever I hear "slow" in conjunction with Hierarchical databinding, it usually turns out to be an overload of data being pushed to the client-side.  Using load on deamnd techniques usually helps quite a bit here.  Not sure if you've investigated these options yet.  You can use the contact link from my blog to send me more specifics, as can anyone else reading.

# May 12, 2008 9:31 PM

Subba Rao said:

Hi,

 I am fine working with the Hierarchical webgrid at runtime. But one problem when I am trying to save, I am not able to access the Child Band Rows. Because the Band object doesn't have a class for Rows. How can I access the Child Band rows without assinging the datasource and creating the bands at runtime. I will be very thankful if someone can help me in this regard.

# July 1, 2008 2:49 AM

Tony Lombardo said:

@Subba - Not sure I completely understand the issue but I'll take a stab at it..  Setting up herarchies at design-time isn't possible unless you use the WebHierarchicalDataSource.  That's simply because there are no datasources capable of doing HierarchicalData for you to bind the grid to.  At runtime, you can access child rows through an individual Row.  So for instance, you can do Grid.Rows[0].Rows[0]  If you need more assistance with this, check out the avilable support resources at http://www.infragistics.com/gethelp

# July 29, 2008 10:42 AM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS