Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Telerik (Kendo) UI for ASP.NET MVC TreeView Issues

I am using MVC 5 and the latest version of Telerik (formerly Kendo) UI for ASP.NET MVC. I am working with hierarchical data. I am attempting to create the TreeView in the _Layout view and populate it with urls or action links.

My current code:

In the _Layout View:

@Html.Partial("_ProductTree")

"_ProductTree" Partial View:

@(Html.Kendo().TreeView().Name("ProductTree")
    .DataSource(d => d
        .Model(m => m
            .Id("ProductId")
            .HasChildren("Categories"))
    .Read(r => r.Action("_ProductTree", "Home")))
    .DataTextField("ProductName"))

Action Method:

[ActionName("_ProductTree")]
public JsonResult GetProductTree()
{
    var products = _productBusinessService.GetProducts();

    var result = products.Select(p => new
    {
        p.ProductID,
        p.ProductName,
        Categories= c.Categories.Any()
    }).OrderBy(t => t.ProductName);

    return Json(result, JsonRequestBehavior.AllowGet);
}

I am having a number of issues:

  1. When I expand a parent node that has children, the TreeView is hitting the action method and appending the entire tree to the child, instead of just displaying the children.
  2. I need to be able to nest the TreeView two-deep, for example Product > Category > Type.
  3. I am trying to figure out how to aggregate or project the data using LINQ to do a two-deep higherarchy.
  4. I tried turning off LoadOnDemand but that made the TreeView call the action method once for each record in the Product list.

I have tried inserting the TreeView Razor code directly into the _Layout view (not using a partial view). I realize that I may need to move the action method into a base controller class and inherit it in every controller to stop it from appending the list to the parent node. If I cant get this working soon, I may have to either use Kendo UI Professional or an open source alternative.

Some of you may be tempted to say that this question has been answered elsewhere. None of the posts I have found address the issues of populating and displaying nested (more than one deep) hierarchical data using the Telerik TreeView.

There is this post

Nested DataSources and TreeView with kendo ui

But it is for the JavaScript version of the TreeView (not the UI for MVC) version and it has not been answered.

Thank you in advance for your help!

like image 364
wayne.blackmon Avatar asked Jul 19 '14 15:07

wayne.blackmon


1 Answers

The solution in code:

The _Layout view:

@Html.Partial("_ProductTree")

or

@RenderSection("productTree", false)

then in the content view

@section productTree
{
    @Html.Partial("_ProductTree")
}

the _ProductTree partial view

@(Html.Kendo().TreeView().Name("ProductTree")
    .DataSource(d => d
        .Model(m => m
            .Id("Id")
            .HasChildren("HasChildren")
            .Children("Children"))
    .Read(r => r.Action("_ProductTree", "Home")))
    .DataTextField("Name"))

I moved the action method to a BaseController abstract class that can be inherited by any controller that needs to display the ProductTree TreeView. The data was pulled from a ProductService and a CategoryService and aggregated using LINQ projection into anonymous objects:

    [ActionName("_ProductTree")]
    public JsonResult GetProductData()
    {
        var products = _productBusinessService.GetProducts();

        foreach (var product in product)
        {
            foreach (var category in product.Categories)
            {
                category.ProductTypes =
                    _productService.GetProductTypes(category.CategoryId);                                           
            }
        }

        var productTreeData = products.Select(p => new
        {
            Id = p.ProductId,
            Name = p.ProductName,
            HasChildren = p.Categories.Any(),
            Children = p.Categories.Select(c => new
            {
                Id = c.CategoryId,
                Name = c.CategoryName,
                HasChildren = c.ProductTypes.Any(),
                Children = c.ProductTypes.Select(t => new
                {
                    Id = t.ProductTypeId,
                    Name = t.ProductTypeName,
                    HasChildren = false
                }).OrderBy(t => t.Name).ToList()
            }).OrderBy(c => c.Name).ToList()
        }).OrderBy(p => p.Name).ToList();

        return Json(productTreeData, JsonRequestBehavior.AllowGet);
    }

The result is a 3-deep, fully populated, sorted Telerik UI for ASP.NET Treeview containing the names and IDs of Product >> Category >> ProductType. Turning LoadOnDemand on or off did not seem to make a difference in this case. It should make a difference when using Bind in a TreeView.

I hope this helps!

like image 184
2 revs Avatar answered Nov 02 '22 21:11

2 revs