Master-Detail with the GridView, DetailsView and ModalPopup Controls

A while back I wrote a post describing how the DetailsView, GridView, UpdatePanel and the AjaxControlToolkit's ModalPopup controls could be used to implement the common Master/Details UI pattern.  I cheated a bit when creating my original example in that I didn't really complete the implementation - the Save button on the popup didn't actually do anything.  Since writing that post I have received a lot of email and a number of people left comments asking me to complete the example - so here it is.  If you plan on reading through this article, I recommend playing around with the demo site to get a feel for how the page works.  All data changes are only persisted to memory, so don't worry about messing up the data set.

Live Demo | Download

image

Scenario

I am sure everyone is pretty familiar with Master/Details style of editing data, but just in case - here is how my page works.  The grid shows 12 rows of customer data.  The far right column in the grid contains a hyperlink that when clicked brings the detail view of the row into focus so the corresponding row can be edited.  The detail view is a popup control and contains a Save and Close buttons.  When close is clicked, the detail popup is dismissed and the user goes back to viewing the main grid.  When they click Save, some simple validation checks are run (all are RequiredFieldValidators for this sample) and the new data values are persisted, and finally the detail popup is dismissed and the main grid is refreshed so that it displays the changes.

Controls

There are quite a few controls that work together for this sample.  Here is a listing of the controls and the role they play.

Control Role
GridView Display the 12 customer rows of data
DetailsView Display the single customer row that is currently being edited
ModalPopupExtender Display the DetailView modally
UpdatePanel Allow the DetailView to be loaded without refreshing the entire page
ObjectDataSource Manage how our UI interacts with the customer data

Customer GridView

The Customer Grid is just a regular GridView.  I have used BoundFields to bind to the data and I am using a TemplateField for rendering the 'Edit' anchor. 

image

When 'Edit' is clicked, I want to show the detail view popup.  To accomplish this I set the CommandName of the 'Edit' button to Select - this will cause the SelectedIndexChanged event to fire on the server.  Inside this event handler, I force the DetailView to databind, passing the datasource it is bound to the ID that corresponds to the row the user clicked.  Finally, I let the UpdatePanel the DetailView is contained in that it needs to update its contents and invoke the Show server side method of my ModalPopupExtender which will cause the popup to be displayed when the partial page is reloaded on the client.

Here are the 2 events handlers that I am using to accomplish this bit of work.  The top event handler fires when 'Edit' is clicked and the explicit call to DataBind forces the DetailView's corresponding ObjectDataSource's Selecting event to fire.  In this handler I use the SelectedIndex of the GridView to fetch the ID the data source needs. 

image

image 

Customer DetailsView

The DetailsView for the individual customer records is also pretty simple - except because I have included RequiredFieldValidators I wasn't able to use the BoundFields and instead I had to explicitly define the EditItemTemplate for each of the fields.

image

Just below the DetailsView, I have 2 buttons that interact with the ModalPopupExtender.  The Close button dismissed the popup without posting back or committing any changes.  The Save button does post back, moves the data out of the DetailsView and back to the ObjectDataSource, hides the ModalPopupExtender and finally causes the main GridView to refresh so it displays the changes.

image

Here is the logic I have wired to the Save button's click handler.

image

Apply a Yellow Fade to the Updated Row in the GridView

And while this has been pretty much nuts and bolds functionality thus far, I couldn't resist trying to spice it up by applying a yellow fade to the row in the main grid that was updated.  To implement this feature, I needed a way to send a bit of information back from the server that let me know what row in the grid was updated.  So my approach was to use the ScriptManager's RegisterDataItem method to accomplish this.  Here is the doc from MSDN:

Sends custom data to a control during partial-page rendering, and indicates whether the data is in JavaScript Object Notation (JSON) format.

Just what I need - so after the Save button is clicked, back in the server side event handler, I call RegisterDataItem and pass the index of the updated row to the GridView.  Then after the partial refresh has occurred back on the client, I extract the row index from the DataItem's collection, use it to find the row that changed and give it a custom CSS class.

So I added the following call to my Save button handler to register the index of the row that was changed.

image

And then added the following JavaScript to my page to track down the corresponding TR element in the rendered table and apply the updated CSS class to the row.

image 

And like magic I get a yellow background applied to the row that was edited.  The background color stays in place for 1.5 seconds then my timeout handler fires and removes it.  A poor man's animation, but the plumbing is in place for me to improve upon.  Below are the screen shots of how it looks.

image

image

That's it.  Enjoy!

TrackBack

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

Comments

Of all the millions of RSS feeds out there on the net, this is the ONLY blog I subscribe to.

Once again, this latest post demonstrates why. Clear, concise, simple and above all, USEFUL.

This is such a sweet example of "useful" AJAX at it's best.

LOVE YOUR WORK, MATT!

T

Seems to be broken

Nice but it does not work on Firefox 2.0

Exactly what I was looking for Matt.. Your a legend as always, thanks again for taking the time to write these examples - This is definitely one of the best blogs on the net!

Hi !

Good, exemple. But it seem very slow at opening and closing the modal. For the basic user it can seem like a bug.

I don't really like the AjaxToolkit modal, I prefere jQuery modal like thickbox, what's you opinion about this ?

Great info Matt. Thx for always having great content for us to learn.

I have been lurking on your blog since you started appearing in Scott Gu's links.

I have been "borrowing" a lot of your code & ideas. I was stuck trying to implement a listview doing all what your doing here...I can't thank you enough (even though your code in C# ;-) ).

Wonderful...please, PLEASE, keep up the good work.

PS> How long before you get all of this together for a book? (hint, hint)

Very nice flair with the row highlight to give the user feedback that their requested action occurred!

That is a great idea and I think I might try a similar approach in my next project if my entry forms don't turn out to be too complex.

Fabulous idea and a great implementation. However, the delay when clicking Edit is a little extreme. I would've probably used an animated indicator, or perhaps just grayed out the screen prior to making the AJAX call.

Great post, I'll be referencing this in the near future.

(PS: Why aren't you tracking your live demos with Google Analytics?)

WONDERFUL.. Thanks very much Matt!

hi,Matt great work.I used same concept but my PM wants that the Modalpopup should be animated like ModalBox or GreyBox.I search many post and example but not find animation effect with Modalapopup extender.
All your posts helps us a lot.
Thanks a lot matt:)
Keep it up

Have you been able to display the Detailsview with the fields positioned on the top and not to the left?

You would think that there would be a ColumDisplay proper that would all you to select Vertical or Horizontal and the would be the end of it.

I was curious if anyone developed a modal popup lookup? You click a link/button
(next to the textbox that needs the lookup value) that opens a popup page where you can search and select from a gridview?
When you select a row it closes the popup and populates the textbox?

@T -
That is one hell of a compliment. Thanks!

@geoff, @Ali Erdoğan -
Can you elaborate on what is broken? I have tested it using FF 2.0.0.14 with no problems.

@Evilz -
My demo site runs a bit slower than I would like - I need to do something about that.

As for jquery versus MS AJAX I would have to say that I like the flexibility of jquery, but I enjoy the stability of MSFT endorsed products. And it is easier to find ASP.NET developers than it is to locate devs that are fluent in jquery. To the company I work for that is a pretty big deal.

@wr -
Glad to help.

I really doubt I would ever write a book. They require a writing style that is too formal for my liking. And besides that it would kill me to labor of the grammer, spelling flow of a tech book. I don't see the ROI in that for the author or the readers. I enjoy writing posts like this one - a live demo, a handful of code snippets and a few paragraphs to glue it all together. Those are the posts I enjoy reading - so thats what I figured I would write.

Thanks for asking.

@Rick Glos -
My thoughts exactly. I am already feeling a follow-up post exploring some other style alternatives.

@Chris M -
Good Luck. Let me know how it turns out.

@Josh -
I swear it was damn fast when it was just me testing it ;). If I write a followup to this post I will add a progress indicator.

I never really thought about tracking my demo site traffic. That would be interesting ...

@Ahmed G -
Thanks Ahmed!

Jignesh -
I explored this a bit a while back. You could try reading this and seeing if it helps you out.

@David -
As far as I know the DV doesn't support that. Of course you could easily do something like that with the new ListView ...

@Cha -
Sounds interesting.

Hi Matt,

Great example! Everything works fine, but when you leave blank required field, and hit Cancel button, you can't display modal popup again. Any ideas how to solve this problem?

Thanks.

hi, Matt.
pls help me in writting above eaxample in case of Sql database,
here u have show it using objectdatasource.
pls tell me hw to do it using sql database.

thanks in advance..
Shailendra

Matt, thanks for your blog. I have been pondering a method for editing. Thanks for the tips.

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 - 101
  • Comments - 1258
  • Recent Comments

    • Kevin wrote: Matt, thanks for your blog. I have been pondering a method for editing. Thanks for the tips....
    • Shailendra wrote: hi, Matt. pls help me in writting above eaxample in case of Sql database, here u have show it using ...
    • Konstantin G wrote: Hi Matt, Great example! Everything works fine, but when you leave blank required field, and hit Can...
    • Matt Berseth wrote: @Ahmed G - Thanks Ahmed! Jignesh - I explored this a bit a while back. You could try...
    • Matt Berseth wrote: @Rick Glos - My thoughts exactly. I am already feeling a follow-up post exploring some other...
    • Matt Berseth wrote: @wr - Glad to help. I really doubt I would ever write a book. They require a writing styl...
    • Matt Berseth wrote: @T - That is one hell of a compliment. Thanks! @geoff, @Ali Erdoğan - Can you ela...
    • Cha wrote: I was curious if anyone developed a modal popup lookup? You click a link/button (next to the textbox...