OK...I've spent too much time floundering on this one, so I'm passing it on to the experts.
My VERY simple ASP.NET MVC (v3 with Razor View Engine) page uses a Telerik Rad Grid control to show some type lists and then I have the associated codes showing in the DetailsView of the grid.
Doing the population is easy. I have a ViewModel for my TypeCodeList type and send it to the strongly typed view to populate the grid. This works GREAT...and the grid looks great - thanks Telerik. However, I added the DetailsView to then populate the child TypeCodes in the same manner. The bad thing is that when my grid populates, I select the triangle on the left to expand the tree and see the child records, nothing is there. BUT, if I select the "Refresh" button on the bottom of the grid, THEN I can hit the triangle and the child records display.
So (in summary), the child records do not show up on the initial load. Only when I select an AJAX refresh of the grid I get the children. Otherwise, it works as required.
I have been trying to see if I can programmatically kick off the refresh via javascrip upon page load. OR if I can get the thing to populate by itself when selected without doing a refresh first - that would be preferable.
Below is my code:
Pertinent Controller Code (I've taken out the update, delete, insert, logging and data access methods)
[HandleErrorWithElmah] public partial class HostController : Controller { /// <summary> /// Index - Home for HostController /// </summary> /// <returns></returns> public ActionResult Index() { return View(); } #region Type List Section /// <summary> /// Gets the list of TypeLists - yea...say that again /// </summary> [GridAction] public ActionResult TypeCodeList() { var model = GetActiveTypeLists(); // Get all of the type lists and send them to the view return View(model); } /// <summary> /// The ajaxified Select /// </summary> /// <returns></returns> [AcceptVerbs(HttpVerbs.Post)] [GridAction] public ActionResult _TypeCodeList() { var model = GetActiveTypeLists(); return Json(new GridModel(model)); } /// <summary> /// Simply a wrapper to get all of the current type list values. /// </summary> /// <returns></returns> private IEnumerable<TypeCodeListViewModel> GetActiveTypeLists() { var model = from p in entityRepository.Find<TypeList>(p => p.IsActive == true) select new TypeCodeListViewModel { TypeListId = p.TypeListId, Name = p.Name, Description = p.Description, IsActive = p.IsActive }; return model; } #endregion #region Type Code Section [AcceptVerbs(HttpVerbs.Post)] [GridAction] public ActionResult _TypeCodeForTypeListAjax(int typeListId) { var model = GetActiveTypeCodes(typeListId); return Json(new GridModel(model)); } /// <summary> /// Simply a wrapper to get all of the current type Code values. /// </summary> /// <returns></returns> private IEnumerable<TypeCodeViewModel> GetAllActiveTypeCodes() { var model = from p in entityRepository.Find<OurLeaguePlay.Models.TypeCode>(p => p.IsActive == true).OrderBy(ord => ord.CodeName) select new TypeCodeViewModel { TypeCodeId = p.TypeCodeId, TypeListId = p.TypeListId, CodeName = p.CodeName, CodeValue = p.CodeValue, Description = p.Description, IsActive = p.IsActive }; return model; } /// <summary> /// Simply a wrapper to get all of the current type Code values. /// </summary> /// <returns></returns> private IEnumerable<TypeCodeViewModel> GetActiveTypeCodes(int typeListId) { var model = from p in entityRepository.Find<OurLeaguePlay.Models.TypeCode>(p => p.IsActive == true && p.TypeListId == typeListId).OrderBy(ord => ord.CodeName) select new TypeCodeViewModel { TypeCodeId = p.TypeCodeId, TypeListId = p.TypeListId, CodeName = p.CodeName, CodeValue = p.CodeValue, Description = p.Description, IsActive = p.IsActive }; return model; } #endregion } Here is my View Code:
(I've taken out all of my failed javascript attempts to try and force the load on page load.)
@model IEnumerable<TypeCodeListViewModel> @using Telerik.Web.Mvc.UI @using Telerik.Web.Mvc @using OurLeaguePlay.ViewModels @{Html.Telerik().Grid<TypeCodeListViewModel>(Model) .Name("TypeLists") .DetailView(details => details.ClientTemplate( Html.Telerik().Grid<TypeCodeViewModel>() .Name("TypeCode_<#= TypeListId #>") .DataKeys(keys => keys.Add(k => k.TypeCodeId)) .Columns(columns => { columns.Bound(o => o.CodeName).Width(40); columns.Bound(o => o.CodeValue).ReadOnly(true).Width(40); columns.Bound(o => o.Description).Width(100); }) .DataBinding(dataBinding => { dataBinding.Ajax().Select("_TypeCodeForTypeListAjax", "Host", new { typeListId = "<#= TypeListId #>" }) .Enabled(true); } ) .Pageable() .Sortable() .NoRecordsTemplate("No Type Codes exist for the selected Type List") .ToHtmlString() ) ) .DataKeys(keys => keys.Add(k => k.TypeListId)) .Columns(columns => { columns.Bound(o => o.Name).Width(100); columns.Bound(o => o.Description).Width(150); columns.Command(commands => { commands.Edit().ButtonType(GridButtonType.Image); commands.Delete().ButtonType(GridButtonType.Image); } ).Width(30); }) .DataBinding(dataBinding => { dataBinding.Ajax().Select("_TypeCodeList", "Host") .Update("UpdateTypeList", "Host") .Insert("InsertTypeList", "Host") .Delete("DeleteTypeList", "Host") .Enabled(true); dataBinding.Server().Select("TypeCodeList", "Host", new { ajax = ViewData["ajax"] }); } ) .Editable(editable => editable.Enabled(true).Mode(GridEditMode.InLine)) .Pageable(page => page.PageSize(10)) .Sortable() .Selectable() .Scrollable(scroll => scroll.Enabled(false)) .NoRecordsTemplate("No Type Lists can be retrieved from the database") .ToolBar(commands => commands.Insert()) .Render(); } Finally...here are the ViewModel classes:
public class TypeCodeListViewModel { [ScaffoldColumn(false)] public int TypeListId { get; set; } [Required(ErrorMessage = "Required")] [StringLength(25, ErrorMessage = "Max Length is 25")] public string Name { get; set; } [Required(ErrorMessage = "Required")] [StringLength(25, ErrorMessage="Max Length is 25")] public string Description { get; set; } [ScaffoldColumn(false)] public bool IsActive { get; set; } } public class TypeCodeViewModel { [ScaffoldColumn(false)] public int TypeCodeId { get; set; } [ScaffoldColumn(false)] public int TypeListId { get; set; } [Required(ErrorMessage = "Required")] [StringLength(25, ErrorMessage = "Max Length is 25")] [DisplayName("Name")] public string CodeName { get; set; } [Required(ErrorMessage = "Required")] [StringLength(25, ErrorMessage = "Max Length is 25")] [DisplayName("Value")] public string CodeValue { get; set; } [StringLength(500, ErrorMessage = "Max Length is 500")] public string Description { get; set; } [ScaffoldColumn(false)] public bool IsActive { get; set; } }