Master-Detail Helper Synchronized with the DataGrid 

This control needs reference to both  MVCControlToolkit.Controls.Core-x.x.x.js,  MVCControlToolkit.Controls.Grid-x.x.x.js and jquery.unobtrusive-ajax.js.

The DetailFormFor Helper and the DetailLink helper allow a Detail View be associated with any row of the DataGrid. Clicking the DetailLink of a row triggers the Ajax retrieval of the details associated with the row record. This way we ca show some more details about the current row and/or update them immediately with Ajax.

We advice to avoid the combined use of both on line editing and edting through the detail view, since the items modified with on line editing are actually updated after the View is submitted while modification done through the detail view are passed immediately, and this may confuse the user. Therefore, pls pass a null edit template to the grid when using the Detail View. 

The DetailLink can be placed in both the Display and Edit templates of the DataGrid:


@Html.DetailLink(Ajax, "Edit Details", DetailType.Edit, "ToDoSubTasks", "Home",
                    new { 
                        id =},


The arguments of the DetailLink are: the Ajax helper of the view, the text to be displayed in the link, the type of detail (either Edit or Display), an Action Method and its  associated Controller names, an object containing all route parameters for the Action method invocation, the optional id of a DOM object to show during the Ajax retrieval,  the optional Html attributes of the link, and the name of a javascript callback that is called with no arguments as soon as the ajax call is performed. The method is invoked via Get. The Partial View returned by the Action method must not wrap its content in any form (neither Ajax or normal) because a wrapper Ajax form is already provided by the receiving DetailFormFor Helper. This choice has been done to allow the same Action method be used both in normal and Ajax calls, thus enhancing the re-usability of Action methods. Since the html created by the call is injected into a pre-existing form, the action methods destined to be used with Detail Form are rquired to return a ClientValidationViewResult.

The DetailFormFor  helper need to be placed out of any form of the main View: 


@Html.DetailFormFor(Ajax, m => m.ToDoList, ExternalContainerType.div,
           "ToDoSubTasks", "Home", null, "isChangedToDo", "isDeletedToDo")


The argument passed to the helper above are: the Ajax object of the View, the collection the DataGrid acts on, the type of container where to receive the Ajax data, Action name and Controller name, the prefix used before the names of the properties returned by the Ajax call, if any, otherwise null, and two CSS classes.

The first Css class (in our case is" ChangedToDo" ) is applied to all properties in the row associated with the details retrived that are discovered to be changed when the Ajax call returns. In other terms if the value retrieved via Ajax is different from the value of the same property in the master row the value in the row is updated with the new value and the above Css class is applied to it. Only the values of the display templates are updated, because they represents the old values. The values entered by the users in edit mode are not updated. This way the user has the choice of either accepting the new values discovered by the Ajax call by pressing the undo button That cancels its corrections or retaining the Ajax retrieved changes. The second Css class is applied to the root of a row that is discovered to be already deleted by the Ajax call. A row is considered deleted if no data field is returned by the Ajax call.

This synchronization behavior is automatcially applied only if both the involved properties are elementary properties and  are rendered either through input fields or through the DisplayField helper. However, it is possible to synchronize complex objects(classes) or Lists, with some additional programming as follows:

  1. All complex fileds needs to be declared explicitely with the toTrack parameter of the Grid helper.
  2. The html that will substitute the html of the complex field in the current row is rendered in the detail View.
  3. You call the DetailFormSyncInfos helper passing it a lambda expression that reference the field to synchronize, and the just created html, as shown below:


@Html.DetailFormSyncInfos(m => m.ToDoRoles, 
                Html.Partial("RoleList").ToString(), false) 


In the example above the field to synchronize is a list of roles, and the partial View "RoleList" renders this list as a dotted list. The last parameter, specifies if the content passed in the previous parameter must be Html encoded or not.

The DetailFormSyncInfos extension method can be used also with simple fields if you want to overrided the default behaviour of the synchronization engine. In particular it is useful when the DisplayField helper renders its content as an img tag. This may happen when rendering booleans or enumerations. The DetailFormSyncInfos extension method has an optional parameter to pass an url to a field rendered as an img tag:


@Html.DetailFormSyncInfos(m => m.Important, ImportanceAlts[1], false, urlValue: ImportanceUrls[1])



In the example above the string passed as second parameter is used as content for the Alt attribute, while the urValue parameter substitutes the url of the img tag.

For an example of synchronization, please see the EditDetailToDo.ascx partial View in the BinariesWithSimpleExamples file.

The DetailFormHelper has also optional arguments to specify Javascript functions to be called OnSucces or OnFailure of the Ajax call. All javascript code returned by the Ajax call is automatically executed: this way controls returned by the calls that rely on javascript may work properly. The submit of the Detail form can be achieved either by a submit button or via the Javascript call of the submit method of the Ajax form. The method used is Post.

The DetailFormHelper accepts also other optional arguments, namely:

  • externalContainerHtmlattributes. An IDictionary<string, object> containing all html attributes to apply to the form root node.
  • clientOnSuccessEdit, clientOnFailureEdit, clientOnSuccessDisplay, clientOnFailureDisplay: the name of javascript callbacks called with no arguments after the ajax call, in case of success or failure. The callback for edit mode and display mode are different.
  • loadingElementId: the id of an element to display during the ajax call performed when the form is submitted with the user edits.
  • detailDialog: If a Dialog object is passed in the optional argument detailDialog, the detail form will appear in a jQuery UI Dialog as soon as a detail link is clicked. This option is available only if jQuery UI is available

The Dialog class contains most of the attributes that control the behavior and appearence of the Dialog:


 	public bool Modal { get; set; }//default false, says if the Dialog is modal
        public bool Stack { get; set; }//default true, if true the dialog will stack on top of other dialog
        public string Title { get; set; }//default string.empty, the title of the Dialog
        public string DialogClass { get; set; }//default null, a css class to add to the dialog
        public bool Draggable { get; set; }//default true, specifies if the dialog is draggable
        public bool Resizable { get; set; }//default true, if resizable
        public string Show { get; set; }//default null, specifies the name of the effect to apply when dialog appear
        public string Hide { get; set; }//default null, specifies the name of the effect to apply when dialog disappear
        public bool CloseOnEscape { get; set; }//default true, the dialog is closed when escape is hit
        public int? MaxHeight { get; set; }//default null
        public int? MinHeight { get; set; }//default null
        public int? MaxWidth { get; set; }//default null
        public int? MinWidth { get; set; }//default null
        public string Position { get; set; }//default 'center', position on the screen. Not numeric positions need to be inclused between ''
        public int? InitialZIndex { get; set; }//default null, initial ZIndex


For more information see here:;

If you are not using jQuery UI, but jQuery Mobile, or Bootstrap, you may trigger the opening of a jQuery Mobile or Bootstrap dialog on the clientOnSuccessDisplay and clientOnSuccessEdit javascript callbacks.

The use of the dialog requires the javascript file jQuery-UI and its relative css style sheet and alo either the old Microsoft Ajax or the jQuery Ajax. 

Download  here a complete application example that shows the pratical use of the DetailFormFor Helper and see its associated tutorial here.

Last edited Jun 22, 2014 at 11:52 AM by frankabbruzzese, version 26


No comments yet.