Bulk Inserting Data with the ListView Control

I am working on a project that needs a new screen for bulk entry tasks.  We have a few business scenarios coming up where we have people inputting 5 to 8 records of data at a time.  I met with a few of our analysts last week and hashed out a rough outline of what they were looking for.  About 10 times or so during the 30 minute meeting some form of the phrase 'kind of like excel' was mentioned.  Our data entry personnel are familiar with excel and our analysts thought an excel styled grid would make a lot of sense.  'An excel grid with a Submit button' was the phrase I had underlined twice in my notes. 

I wasn't too worried about the grid's styling, but I wasn't quite sure what the best way to handle the 'bulk insert' requirement.  Most of our other grids require an explicit mouse click to insert an item - and often times this click includes navigating the user to a separate page that is made to handle inserts.  Of course for mass data entry tasks this can get a little old - tabbing through the cells is much nicer.  So I took my notes back to my desk and started building a small prototype.  You can check out the live demo to watch the grid in action.  And a few of my implementation notes can be found under the screen shots below.

Live Demo (IE6, IE7, FF, Opera) | Download

image 

Configuring the ListView

My excel styled grid only has one mode - bulk insert.  It would also support mass updating as well, but for our use cases this is a one way data stream.  I want to use the ListView because I like how the templates are structured, but the ListView doesn't natively support bulk inserting data (the ListView supports defining an InsertItemTemplate, but the ListView will only render this template once - so this template isn't useful for my scenario).  I decided I would try using the regular ItemTemplate, but render elements that support editing instead of the usual read-only controls (i.e. TextBox's instead of Labels).  I still use the Bind syntax because I want 2 way databinding, but because I am using the ItemTemplate for an insert scenario I will be responsible for telling the ListView when my data needs to be moved out of the controls and back to my data source.  Below is the markup for my ListView.

image

 

Setting Up My DataSource

Next, I setup my data source.  For this example I am using the ObjectDataSource control.  When my data source is first bound to the ListView, I want to render placeholder objects for 8 records (i.e. I want my grid to show 8 empty rows by default).  So when my Select method fires, I return a collection that contains 8 Customer objects that have their property values set to their default values (null strings for my example).

image

Next, I handle the Submit button's click event handler and loop through all of the ListViewDataItems and invoke the ListView's UpdateItem function which will cause the Update method on my ObjectDataSource to fire - moving the data back out from the controls and back into memory.  Finally, after the data is moved back to memory, I persist the batch to the database (for the demo I am persisting it to memory, but when this page goes live it will obviously be put in the database).

image

To make sure I don't persist records with all empty values, I added a validation check to my Customer business object that makes sure the object has at least one data value before the row is submitted.  If validation passes, I move the customer data into the database.

image

 

Toggling the DataTable's Skin

For a bit of flair I included a couple of radio buttons for changing the grids theme from the default 2003 style excel shown below (found a nice article here on creating this skin) to the 2007 version which is a bit softer (see screen shot at the beginning of the article). 

image

To change the grids skin I attached event handler's to the radio button's click events and use the Sys.UI.DomElement.addCssClass and removeCssClass to toggle the CSS class that is applied to the grid.  Below is the JavaScript that does this bit of work for me. 

image

That's it.  Enjoy!

TrackBack

TrackBack URL for this entry:
http://mattberseth.com/blog-mt/mt-tb.fcgi/119

Comments

Another excellent post! It's nice to see you "express yourself" and not just settle for the bare minimum amount of flair ;)

Now excuse me while I go watch that movie!

Great Article...I learn a lot Thanks :)

Very nice... Thanks Matt.

Great article.

Very clean and straight forward.

Pete

Once again, your posts are incredibly useful; well thought out and applicable to real-life issues.

Keep it up.

Hi Matt,
Yet again, bang on target.

Really, a very good article.

Thanks.

Matt,

This is a great example, and something I was working on myself. I'm a bit confused with your use of delegates however in the Javascript code. It was my understanding that the main reason for wrapping delegates in Javascript was to allow for disposing and to allow instance methods to serve as delegates. Since you aren't using the returned delegate at all from the Function.createDelegate() call, I'm not sure what the point of using it is. Seems like the following would be equivalent (with less code):

$addHandler($get('rdoOffice2007'), 'click', onSkinChanged());
$addHandler($get('rdoOffice2003'), 'click', onSkinChanged());

Great stuff. If you could get it to accept multiple cells pasted from Excel, it'd be outstanding!

Nice
is there a VB version

Thanks again for another neat example Matt. The excel skinning functionality takes this yet another notch in being user-friendly. I was thinking of how to modify this for export to Word/RTF format?

In a Borat Voice:

Very Nice...I Like

What's the purpose of the delegate in the Save method?

Awesome!

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)

This Blog

  • Email Me
  • RSS
  • Atom
  • Entries - 102
  • Comments - 1276
  • Recent Comments

    • Agha wrote: Awesome!...
    • Tim wrote: What's the purpose of the delegate in the Save method?...
    • JoeBo wrote: In a Borat Voice: Very Nice...I Like...
    • Yubi wrote: Thanks again for another neat example Matt. The excel skinning functionality takes this yet another ...
    • AsX wrote: Nice is there a VB version...
    • Anthony wrote: Great stuff. If you could get it to accept multiple cells pasted from Excel, it'd be outstanding!...
    • Michael McGuire wrote: Matt, This is a great example, and something I was working on myself. I'm a bit confused with your...
    • Vish wrote: Hi Matt, Yet again, bang on target. Really, a very good article. Thanks....