Modifying Data with the ListView's EditItemTemplate

I am lovin' the total control the ListView control is giving me.  This past week a link to Telerik's new RadGrid control was floating around the office - and the general consensus was that the in-line editing capabilities control was pretty cool.  And I completely agree - the in-line edit feature is pretty useful.  But ... you don't need to buy the RadGrid to create a grid like this.  ASP.NET 3.5's ListView control provides excellent out of the box support for scenarios like this.

Check out the screen shot below (or even better, open up my live demo).  This grid provides the same in-line editing support as the RadGrid, it is incredibly flexible if you want to tweak the layout, and best of all there is absolutely zero codebehind logic!  Did I mention I am lovin' the new ListView?

Below are some of the implementation details - read on if you are interested.

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

image

 

Creating the ListView - Defining the Template Shells

The first thing I like to do when using the ListView is to stub out the control and fill in the templates that I plan on using with a few comments regarding what bit of HTML these templates will be responsible for rendering.  For this example, I know that I will need to make use of three templates: the LayoutTemplate for setting up the overall structure, an ItemTemplate for defining the read-only item template and finally an EditItemTemplate that contains the template for the item that is currently being edited.

   1:  <asp:ListView ID="ListView" runat="server">
   2:      <LayoutTemplate>
   3:          <!-- 
   4:              Define the core structure for my grid
   5:              for this example this will be a TABLE element
   6:          -->
   7:      </LayoutTemplate>
   8:      <ItemTemplate>
   9:          <!-- 
  10:              Define the bit of HTML to render for each object in my datasource 
  11:              for this example, this will be a TR element
  12:          -->
  13:      </ItemTemplate>
  14:      <EditItemTemplate>
  15:          <!-- 
  16:              Define the core structre for my grid 
  17:              for this example, this will be 2 TR's,
  18:              one that displays the header information and
  19:              another that contains a nested TABLE that contains
  20:              the INPUT elements
  21:          -->
  22:      </EditItemTemplate>
  23:  </asp:ListView>

 

Creating the ListView - Filling in LayoutTemplate

I want my grid to render as an HTML table.  So I use the LayoutTemplate to define the grids column header values as well as create the placeholder element for my other templates. 

   1:  <asp:ListView ID="ListView" runat="server">
   2:      <LayoutTemplate>
   3:          <table class="gridview" cellpadding="0" cellspacing="0">
   4:              <tr class="header">
   5:                  <th></th>
   6:                  <th>ID</th>
   7:                  <th>Name</th>
   8:                  <th>Address</th>
   9:                  <th>Zip Code</th>
  10:                  <th>Phone</th>
  11:              </tr>
  12:              <tr id="itemPlaceholder" runat="server" />
  13:          </table>
  14:      </LayoutTemplate>
  15:      <ItemTemplate />
  16:      <EditItemTemplate />
  17:  </asp:ListView>

Creating the ListView - Filling in the ItemTemplate

And below is the markup I am using for my ItemTemplate.  Nothing too magical here, just specifing that each object in my datasource will be represented within the TABLE as a row.  There are 3 items here to take note of ...

  • The ListView does define an AlternatingItemTemplate, but I personally don't find it really all that useful.  The only variation I usually want between my ItemTemplate and the AlternatingItemTemplate is the CSS class that is applied to the row - and there is no need to redefine your complete ItemTemplate to achieve this.  Instead you can dynamically set the CSS class value of the TR element using the following expression:

<%# Container.DataItemIndex % 2 == 0 ? "row" : "row alt" %>

Which will render <tr class="row" /> for even rows and <tr class="row alt" /> for odd ones

  • I have include a LinkButton to the template and set the CommandName property to Edit.  This will automatically (i.e. no extra code required) cause a postback and lets the ListView know that it needs to render the EditItemTemplate for the data item that is bound to the current row.
  • Notice that I am using the ?? operator to explicitly set the value of the cell to a non-breaking space if the property value is null.  This avoids the weirdness of not having styles applied to empty cells (i.e. <TD></TD>). 
   1:  <asp:ListView ID="ListView" runat="server">
   2:      <LayoutTemplate />
   3:      <ItemTemplate>
   4:          <tr class='<%# Container.DataItemIndex % 2 == 0 ? "row" : "row alt" %>'>
   5:              <td class="command">
   6:                  <asp:LinkButton 
   7:                      ID="btnEdit" runat="server" 
   8:                      Text="Edit" CommandName="Edit" 
   9:                  />
  10:              </td>
  11:              <td><%# Eval("ID") %></td>
  12:              <td><%# Eval("ContactName") ?? "nbsp;" %></td>
  13:              <td><%# Eval("Address") ?? "nbsp;" %></td>
  14:              <td><%# Eval("ZIPCode") ?? "nbsp;" %></td>
  15:              <td><%# Eval("Phone") ?? "nbsp;" %></td>
  16:          </tr>    
  17:      </ItemTemplate>
  18:      <EditItemTemplate />
  19:  </asp:ListView>

Creating the ListView - Filling in the EditItemTemplate

When an item is being edited, I want to render 2 TR's.  The first one displays what was in the original ItemTemplate, except the data values are in a bold font.  In the second TR I want to render a nested 3x3 TABLE that displays the additional attributes of each item that can be edited.  Besides these input elements, I also want to allow the user to save or cancel their changes.  Below is a sample screen shot ...

image

Below is the markup for my EditItemTemplate.  Again, there are a few things to notice ...

  • Like I mentioned before, I am actually rendering 2 TR's for the same data item.  The first one is virtually identical to the one the ItemTemplate is configured to render as well.  The only different is that I have applied a custom CSS class to this row called edit-info that allows me to use CSS to control some of the display attributes (like setting the font-weight to bold).
  • I am also using an expression to dynamically add the first class to the row as well when it is the first data bound item.  This allows me to not apply the dashed border when the first row in the grid is being edited (this didn't look very good).
  • I have included LinkButtons that have the CommandName attribute's set to Save and Cancel that tell the ListView when to save or abort the changes.  When the Save button is clicked the ListView coordinates with the datasource to get the changes persisted (for this demo, the changes are in-memory only)
   1:  <asp:ListView ID="ListView" runat="server">
   2:      <LayoutTemplate />
   3:      <ItemTemplate />
   4:      <EditItemTemplate>
   5:          <tr class='edit-info <%# Container.DataItemIndex == 0 ? "first" : string.Empty %>'>
   6:              <td class="command">
   7:                  <asp:LinkButton ID="btnEdit" runat="server" Text="Edit" CommandName="Edit" />
   8:              </td>
   9:              <td><%# Eval("ID") %></td>
  10:              <td><%# Eval("ContactName") ?? "nbsp;" %></td>
  11:              <td><%# Eval("Address") ?? "nbsp;" %></td>
  12:              <td><%# Eval("ZIPCode") ?? "nbsp;" %></td>
  13:              <td><%# Eval("Phone") ?? "nbsp;" %></td>
  14:          </tr>            
  15:          <tr>
  16:              <td class="edit" colspan="6">
  17:                  <div class="details">
  18:                      <div class="header">Edit details for '<%# Eval("ContactName")%>'</div>
  19:                      <table class="detailview" cellpadding="0" cellspacing="0">
  20:                          <tr>
  21:                              <th>ID</th>
  22:                              <td>
  23:                                  <asp:Label 
  24:                                      ID="lblID" runat="server" 
  25:                                      Text='<%# Bind("ID") %>' />
  26:                              </td>
  27:                              <th>Name</th>
  28:                              <td>
  29:                                  <asp:TextBox 
  30:                                      ID="txtName" runat="server" 
  31:                                      Text='<%# Bind("ContactName") %>' />
  32:                              </td>
  33:                              <th>Title</th>
  34:                              <td>
  35:                                  <asp:TextBox 
  36:                                      ID="txtTitle" runat="server" 
  37:                                      Text='<%# Bind("ContactTitle") %>' />
  38:                              </td>
  39:                          </tr>
  40:                          <tr>
  41:                              <th>Address</th>
  42:                              <td>
  43:                                  <asp:TextBox 
  44:                                      ID="txtAddress" runat="server" 
  45:                                      Text='<%# Bind("Address") %>' />
  46:                              </td>
  47:                              <th>City</th>
  48:                              <td>
  49:                                  <asp:TextBox 
  50:                                      ID="txtCity" runat="server" 
  51:                                      Text='<%# Bind("City") %>' />
  52:                              </td>
  53:                              <th>State</th>
  54:                              <td>
  55:                                  <asp:TextBox 
  56:                                      ID="txtState" runat="server" 
  57:                                      Text='<%# Bind("State") %>' />
  58:                              </td>
  59:                          </tr> 
  60:                          <tr>
  61:                              <th>ZIP Code</th>
  62:                              <td>
  63:                                  <asp:TextBox 
  64:                                      ID="txtZIPCode" runat="server" 
  65:                                      Text='<%# Bind("ZIPCode") %>' />
  66:                              </td>
  67:                              <th>Phone</th>
  68:                              <td>
  69:                                  <asp:TextBox 
  70:                                      ID="txtPhone" runat="server" 
  71:                                      Text='<%# Bind("Phone") %>' />
  72:                              </td>
  73:                              <th>Company</th>
  74:                              <td>
  75:                                  <asp:TextBox 
  76:                                      ID="txtCompany" runat="server" 
  77:                                      Text='<%# Bind("CompanyName") %>' />
  78:                              </td>
  79:                          </tr>                                                        
  80:                      </table>
  81:                      <div class="footer command">
  82:                          <asp:LinkButton 
  83:                              ID="btnSave" runat="server" 
  84:                              Text="Save" CommandName="Update" 
  85:                          />
  86:                          <asp:LinkButton 
  87:                              ID="btnCancel" runat="server" 
  88:                              Text="Cancel" CommandName="Cancel" 
  89:                          />
  90:                      </div>
  91:                  </div>
  92:              </td>
  93:          </tr>
  94:      </EditItemTemplate>
  95:  </asp:ListView>
 

That's it.  Enjoy!


TrackBack

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

Listed below are links to weblogs that reference Modifying Data with the ListView's EditItemTemplate:

» Create In-line Data Editing with the ASP.NET 3.5 ListView Control from DotNetKicks.com
You've been kicked (a good thing) - Trackback from DotNetKicks.com [Read More]

Comments


Posted by: Tor Christian on May 22, 2008 12:00 AM

You have learned me alot about web development!

Thank you for making ready to use,good looking and understandable examples :)
Keep up the good work!

Hi Matt,
You know all these great examples you keep posting, they could really make up an entire book (if not two or more). A kind of "cookbook", think about it? Cause I love your articles and Im sure Im not the only one. Your blog is a superb resource for ASP.NET developers, thank you and keep it up!

Posted by: Bill on May 22, 2008 12:00 AM

Matt,

You might want to take the edit button out of the EditItemTemplate so as not to confuse users.

Thank you again for all your work and wiliness to share. Yours is the first feed I look at to see if there is something new.

Bill

This is great! Keep it coming; Thanks

Wow. Looks great. Thanks for the great post again.

+1 Great stuff.

Posted by: apan on May 23, 2008 12:00 AM

great article!??, matt

Posted by: Chris on May 23, 2008 12:00 AM

Who needs RAD if youve got Matt?

I am really amazed with your articles.. Super work Matt!

Im using the asp.net mvc:

I suspose in the edit template I can use my jquery ajax form post?

If listview is :
1. viewstate free
2. postback free

then I would use it :)

Thanks for your continual great posts, Id like to see some that work outside of just webforms?

Posted by: Kasim on May 25, 2008 12:00 AM

Great stuff as always.

Posted by: Murali on May 28, 2008 12:00 AM

Hi,

Its nice to your Design and Edit opt .in the Gridview
Thanks

@Tor Christian - No problem, thanks for the comment.

@TimothyP - My thoughts exactly. Check out this out

@Bill - I played around with disabling it and even moving the Save/Close buttons to this location, but I thought leaving the Edit button the best option. I will try removing it all together and seeing how that looks.

Steve -
I hope to write a few posts on MVC soon ...

Great article!

Posted by: ibram on June 4, 2008 12:00 AM

Hi Matt,
this is a great site with very useful articles.
I have two questions regarding the listview control.
Ive created a listview that loads an user control to its item template dynamically. Is it possible to load a user control to its layout template too? I was not able to do that. The second and more important issue is: I have a LinkButton in the user control that should fire a command event but it doesnt fire anywhere. Is this not possible?
Thank you.
ibram

If you want some fun, add the and try to add a dropdownlist and bind it to a LINQ query. Or, even try to populate the dropdownlist in the backend. I couldnt seem to get a handle on drop down list from of any of the existing events (except ones that occur after you click the insert button)

Posted by: Randy Bigbie on July 7, 2008 12:00 AM

Matt great posting for a starter. Can you take it one more step further? Can you make one of the fields a drop down list with a "- Select One -" added as one of the items to choose from. Basically I would like to see a better real world example using drop downs in the edit and insert template. Most real world applications have relational data that the user choose from, can you add to the example? Of course I would want LINQ2SQL to be used for the population of the drop downs.

I did learn one thing on my search and that is:

you can setup your drop down like the following in order to add a "- Select One -" to the top of your databound list like the following:

Any help would be much appreciated on how to use events to set the default selected item for when editing and inserting. Thanks!

Posted by: Frank on July 22, 2008 12:00 AM

Hi I was wondering if you know why this is happening: I have a details page that contains a DetailsView control to display a record selected from a master page. Below the DetailsView I have a ListView control that grabs related content to the record displayed by the detaislView. Everything shows up properly, however, when I go to insert a record or page thru the records of the ListView, I loose the DetailsView all together, it disappears from the page. How can I have the DetailsView stay on the page as I interact with the ListView? Please advise.

Posted by: Serge on August 5, 2008 05:30 PM

Matt, great post. I love working with ListViews. There is only 1 huge drawback to ListViews (with DataPager) though....It doesn't support server side paging.

For example...I can write a stored procedure that utilizes Common Table Expressions (CTE) that returns only a "page" of data when you pass in the RowIndex and PageSize....Then I create a strongly typed dataset. Drop a GridView on the forum assign a few properties and it takes care of the paging for me without doing anything else. Unfortunately ListView along with a DataPager cannot do that....

Posted by: Henry on August 20, 2008 11:02 AM

Once again you describe exactly what I want to do in a very easy to understand way, the live demos and the downloadable code are a huge plus.

Thanks for all your effort in explaining a newbie to ASP.NET like me how to make really cool functionality elegantly!
Posted by: mesut demir on August 21, 2008 03:40 AM

Hi Matt,

this is a good example... I looked at your examples but couldn't find a listview/gridview with Insert/Update/Delete function all-in in 1 example...

when you have time would you provide also an example with these functions all-in-one example.

maybe in this example you can add the insert functionality???? :)

thanks for your great great examples...

I'm learning from your examples: CSS, Linq, and C#..

cheers
mesut

Cool stuff. Thank you very much!

Thanks Matt. Great and simple. I had followed this http://www.dotnetfunda.com/articles/article121.aspx and everything is working great, but I noticed in your demo that clicking Edit and Save button is not refreshing the whole page, are you using AJAX? I didn't see any code for that in your post here.

Thanks
Raja

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.)

Consulting Services

Yep - I also offer consulting services. And heck, I'll do just about anything. If you enjoy my blog just drop me an email describing the work you need done.

Recent Comments

  • Raja wrote: Thanks Matt. Great and simple. I had followed this <a href="http://www.dotnetfunda.com/articles/arti...
  • ramil joaquin wrote: Cool stuff. Thank you very much!...
  • mesut demir wrote: Hi Matt, this is a good example... I looked at your examples but couldn't find a listview/gridview ...
  • Henry wrote: Once again you describe exactly what I want to do in a very easy to understand way, the live demo...
  • Serge wrote: Matt, great post. I love working with ListViews. There is only 1 huge drawback to ListViews (with Da...
  • Frank wrote: Hi I was wondering if you know why this is happening: I have a details page that contains a DetailsV...
  • Randy Bigbie wrote: Matt great posting for a starter. Can you take it one more step further? Can you make one of the f...
  • Michael Munnis wrote: If you want some fun, add the and try to add a dropdownlist and bind it to a LINQ query. Or, even ...