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.

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.
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.
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.
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.
Here is the logic I have wired to the Save button's click handler.
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.

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.
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.
That's it. Enjoy!
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 its 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 dont really like the AjaxToolkit modal, I prefere jQuery modal like thickbox, whats 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 Gus links.
I have been "borrowing" a lot of your code and ideas. I was stuck trying to implement a listview doing all what your doing here...I cant 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 dont turn out to be too complex.
Fabulous idea and a great implementation. However, the delay when clicking Edit is a little extreme. I wouldve probably used an animated indicator, or perhaps just grayed out the screen prior to making the AJAX call.
Great post, Ill be referencing this in the near future.
(PS: Why arent 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 dont 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 doesnt 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 cant 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.
Hi Matt I have been trying to implement this modal edit interface and i have been able to successful show the details view in the modal popup but there is a network delay that last about 3 to 4 seconds and i would like to show a progress animiation like you had in the live demo of the previous version of this code. Is there any way you could help me with this. Becuase everthing else works like a peach. If i could fix that that would save my life.
please tell me how to update the record if the database is in sql server...u use objectdatasource.
I used CustomValidator to use server side validation in place of the RequiredFieldValidators in the example for Customer DetailsView. However in edit mode, ServerValidateEventArgss Value returns the old value when a value was changed in a textbox field, not the changed value. Is it because the validator was used in the details view? How do I get the changed value?
Matt,
I amtrying to build a samll application in Visual studio 2005, with mater detil to three levels. I have completed the DB design and build the app using VB. However, I am having a hard time to save/update data in my detail forms. Can you give some insight?
PS - I can send uou the code, if necessary.
Thanks,
George.
do you have any sql db version?
Just buy Telerik RadControls for ASP.NET AJAX, use the RadGrid, and be done with it. All the functionality you are trying to do is built-in w/ the RadGrid - very little code required.
Many thanks. Ive been wanting to do exactly this for a while.
I had the same problem as Konstantin - if you left a validation error on the popup and pressed cancel, the popup wouldnt show again.
I think this is a DetailsView bug. I was able to fix it by using a custom form. Ive uploaded my changed code at http://david.safitech.com/?p=30.
The code also shows Insert Item capability and has Progress indicators.
Fantastic post,
Ive been searching such example for 3 hours. Finally a good working version with all my demands.
Thank you very much!
Excellent work! Do you have an example for adding the details (or formview) dynamically inside the modalpopup? I am doing this but cant seem to get the events to fire.
Thanks.
instead of this eventhandler -
protected void OdsCustomerDetail_Selecting(object sender, ObjectDataSourceSelectingEventArgs e)
{
// set the input parameter to the value of the selected index
e.InputParameters["id"] =
Convert.ToString(this.gvCustomers.DataKeys[this.gvCustomers.SelectedIndex].Value);
}
You can simply add this for OdsCustomerDetail -
Type="String" />
The above will grab the Id (DataKey) of the gridview and use it for the select parameter.
Nice article, Matt.
In the SelectParameters section of odsCustomerDetail, add a new ControlParameter and set the ControlID to gvCustomers, Name to Id, PropertyName to SelectedValue and Type to Int32. You can get rid of the OdsCustomerDetail_Selecting eventhandler
When I pasted the code here, its not showing up. Thats why I spelt it out.
Very good post. I was playing with it. It works OK with one problem for me. When I click save, data is updated, Gridview refreshed, ModalPopUp disappears but the rest of the the page stays disabled as if ModalPopUp is still there.
I tried it in IE and FF. Both the same. Any idea why?
Anyway, thanks for the post.
This is a great solution to a problem Ive been looking to get solved.
Would the solution be any different if your GridView contained more templated columns containing a LinkButton, in addition to the Edit Column which contains the LinkButton for firing the ModalPopup?
I have such a situation and Im seeing the problem where, in applying the solution youve presented here, *none* of the LinkButtons in the GridView now fire!
Any ideas on what the issue could be?
Could you provide some code on how you would handle doing inserts with the detailsview in the modal popup.
Would you just use a button to display the popup? I have tried doing this but couldnt get the details view to cooperate.
So can Detailview be replaced by another panel with Gridview?
may i will get same thing with single pop up why to use this many pop ups
please tell if i use database in sql server 2005...and when i use jst to display detail..my page is posting back..so please help me where i m mistaken
Many thanks for there solution. However I had the same problem as Raja. Is it because of MasterPage?
i can explain why links stop working when you close the modal, but i dont know how to fix it. if you leave a field blank on the details view and then cancel the modal, the required filed validator is going to fire whenever you try to postback the page. since every linkbutton on the page is a postback, they all stop working because the field validator is firing and stopping the postback. only problem is, you cannot see it because canceling the modal made it invisible, but it is still there on the page. any ideas?
Very nice post. One thing is missing is to add a new record using the same detailsview. Can you add it. Also there are changes in Net 3.5
how we will get the details of gridview in details view by using the modal popup extender control of ajax in dotnet?
please post the answer immediately to my mail id-which i have mentioned at the above
Thanks for the Nice Post..
Please continue for the smart post...
Best of Luck
Hi,
This is a nice sample but I have one thing that bothers me a lot: when editing the details for a business object (i.e.: Customer in your example) the user doesnt really need or want to see the ID of the field most of the time.
I set the Visible property of the ID field from the DetailsView (dvCustomerDetail) and the Update operation does not work and that is because the ID passed back is "0".
Maybe I am missing something but do you have any idea on how to achieve this (hiding the ID field and be able to update with the changes)?
Thank you a lot!
Marius
Great article, thanks!
Im also having the same issue as Eka and Raja, with or without using a MasterPage. My data saves and the popup disappears, but Im left with a disabled page.
Ive noticed that in the Status Bar of FF, the following is left displayed:
javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("btnSave", "", true, "", "", false, true))
rather than display Done, as you would normally see following the button being clicked.
Any ideas?
It works OK with one problem for me. When I click save, data is updated, Gridview refreshed, ModalPopUp disappears but the rest of the the page stays disabled as if ModalPopUp is still there.
I tried it in IE and FF. Both the same. Any idea why?
Anyway, thanks for the post.
One problem with using a DetailsView and DataKeyName property on GridView is that you get the infamous MAC Viewstate validation failed bug. Does anyone happen to know of a fix for this. Matt, I can reproduce this error on your test page (Click on UI elements quickly on load). Does anybody happen to know of a fix for this error??? I have never seen a reliable one.
As Muhammad above I would love if you could expand the example to include a bit on how to ADD a new record - or just hint at the technique to do so.
I guess, InsertItemTemplate in the FormView control - but how to get there when using ModalPopup.
Would be very helpful - thank you.
Firstly i thanks for your solutions...
i use same code in my UserControl ...
but in this Linkbutton Click Event not fire...
thats my code
TR.updated TD
{
background-color:yellow;
}
.modalBackground
{
background-color:Gray;
filter:alpha(opacity=70);
opacity:0.7;
}
// attach to the pageLoaded event
Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(pageLoaded);
function pageLoaded(sender, args) {
// the data key is the control's ID
var dataKey = '';
var updatedRowIndex = args.get_dataItems()[dataKey];
// if there is a datakey for the grid, use it to
// identify the row that was updated
if(updatedRowIndex){
// get the row that was updated
var tr = $get(dataKey).rows[parseInt(updatedRowIndex) + 1];
// add the 'updated' css class
Sys.UI.DomElement.addCssClass(tr, 'updated');
// remove the css class in 1.5 seconds
window.setTimeout(function(){
Sys.UI.DomElement.removeCssClass(
tr,
'updated'
);
}, 1500);
}
}
DataKeyNames="Id" AutoGenerateColumns="false" BorderWidth="0" Width="100%"
OnRowDataBound="GridView1_RowDataBound" OnSelectedIndexChanged="GridView1_SelectedIndexChanged">
'
Font-Bold="true" Font-Underline="true" CommandName="Select">
' Font-Size=XX-Small>
'>
TargetControlID="btnShowPopup" PopupControlID="pnlPopup"
CancelControlID="btnClose" BackgroundCssClass="modalBackground"
/>
Rishi
Text="Close" CausesValidation="false" />
TypeName="BLLEventMaster" OldValuesParameterFormatString="original_{0}">
------------------------CodeBehind-------------
protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
this.updPnlCustomerDetail.Update();
// show the modal popup
this.mdlPopup.Show();
}
Hi,
I am trying the above. But found few problems. I have enabled the javascript error. So when i run the application i am getting an error " sys " not defined.
I dont have any clue to solve it
One more question.
Suppose i have a gridview which consits of 25 records and
i want the modal popup to block only the griview section not the screen . is it possible?
Please help.
Hi,
I'm looking into this and realised I had to do some work in order to get this behaviour to work with a sqlserverdatasource, so I'd appreciate an example using that as well (although I've got it to work now myself).
I realise now that if I turn sorting on, the fade effect gets to the wrong row if I have the gridview sorted on the field that I'm changing. (That is, if I have the gv sorted on customers and I change a customer's name, then the original row gets yellow instead of the data in the new position.)
Other than that, this seems to be a great piece of work!
Petter
Thanks Matt! This really helped me out! This was my first time with AJAX :o)
For the people asking how to do it in sql, here is what I did:
I added this to my GridView's Details Source:
"
SelectCommand="SELECT [ID], [Unit], [Driver], [Year], [Make], [Model], [Type] FROM [myTable]">
And my DetailsView's Source:
"
SelectCommand="SELECT [ID], [Unit], [Driver], [Year], [Make], [Model], [Type], FROM [myTable] WHERE [ID]=@ID">
Instead of putting protected void OdsCustomerDetail_Selecting I put it in my aspx code ... that is what the Select Parameters are above. I tell it to control the GridView1
Hope that helps answer those questions! I am writing this in a hurry & hopefully didn't forget anything!
I tried to run the demo and got this message when I clicked on Edit:
Webpage Script Errors
User Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.21022; .NET CLR 3.5.30428; .NET CLR 3.5.30729; .NET CLR 3.0.30618)
Timestamp: Sat, 27 Sep 2008 14:09:36 UTC
0.
Message: Sys.WebForms.PageRequestManagerServerErrorException: Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster, ensure that configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster.
Line: 4724
Char: 21
Code: 0
URI: http://mattberseth2.com/master_details_II/default.aspx
Hey Matt,
You are the best of the best...I havent seen anyone taking so much time to create all those intellectual fancy stuff.....Kudos to you my friend....Keep it going...
Good Luck,
Bharath
Great article as always. I was wondering how this can be accomplished. Very clearly explained.
Hey Matt,
Excellent article...I have on question though I downloaded the code and adapted it to my project that is based on Subsonic but I get an error.
Sys.WebForms.PageRequestManagerServerErrorException:
ObjectDataSource 'odsCompanyDetail' could not find a non-generic method 'FindById' That has parameter: 'id'.
All I did when adapting was using the subsonic collections and functions for getting data from the database...is it possible for you to take a few minutes to have a look at it if I sent you the code. I think its something with the ODS but is it possible its something with the Javascript perhaps?
Thanks,
Magnus
Hi Matt,
What you outlined in this article is exactly what i was looking for. I have been trying see if the elements of AJAX toolkits & the detailsview work together. BUT...
I am working in VB.net & i can't seem to adapt your code to work in VB.net.
So is it a case of this code only works in C#? Or can it be manipulated to work for vb.net? If you know how to make this work in VB.net then please do let me know.
Thanks,
Shuja
Hi Matt,
I can't seem to get sorting to work on this GV. Shouldn't it be a simple "Enable Sorting = True" in the properties column of the GV? I've gotten it to work on other GV's. Is there something in here that prevents that? Or is it not possible because it is XML rather than SQL DB?
Hi
This example is very good but when I use autopostback dropdown list pop up extender goes away how can I solve this problem thanks....
Hi Matt,
Your code works fine with dotnet but when i try to include the same code using custom control .ascx page in Sharepoint site webpart. it si not working any workaround will be apreciated.