Your search did not match any results.

Tree List - Load Data on Demand

The TreeList can load a remote dataset dynamically as a user expands nodes. The dataset must have a plain structure.

Backend API
@(Html.DevExtreme().TreeList() .ID("treelist") .DataSource(new JS("treeList_dataSource")) .KeyExpr("id") .ParentIdExpr("parentId") .HasItemsExpr("hasItems") .ShowBorders(true) .RemoteOperations(r => r.Filtering(true)) .Columns(columns => { columns.Add() .DataField("name"); columns.Add() .DataField("size") .CustomizeText("treeList_size_customizeText") .Width(100); columns.Add() .DataField("createdDate") .DataType(GridColumnDataType.Date) .Width(150); columns.Add() .DataField("modifiedDate") .DataType(GridColumnDataType.Date) .Width(150); }) .RootValue("") ) <script> function treeList_size_customizeText(e) { if(e.value !== null) { return Math.ceil(e.value / 1024) + " KB"; } } var treeList_dataSource = { load: function(options) { return $.ajax({ url: "@Url.Content("~/api/TreeListData")", dataType: "json", data: { parentIds: options.parentIds } }).then((result) => ({ data: result })); } }; </script>
using System.Web.Mvc; using DevExtreme.MVC.Demos.Models.SampleData; namespace DevExtreme.MVC.Demos.Controllers { public class TreeListController : Controller { public ActionResult LoadDataOnDemand() { return View(); } } }
using System; using System.Linq; using System.Net.Http; using System.Web.Http; using System.Web.Hosting; using System.IO; using System.Web.Http.Cors; namespace DevExtreme.MVC.Demos.Controllers.ApiControllers { [EnableCors(origins: "*", headers: "*", methods: "*", SupportsCredentials = true)] public class TreeListDataController : ApiController { [HttpGet] public HttpResponseMessage Get([FromUri] string[] parentIds) { var rootPath = HostingEnvironment.MapPath("~").TrimEnd('\\'); var childNodes = parentIds.SelectMany(parentId => { var parentPath = String.IsNullOrEmpty(parentId) ? rootPath : Path.Combine(rootPath, parentId); return Directory.EnumerateFileSystemEntries(parentPath); }) .Where(path => Path.GetFullPath(path).StartsWith(rootPath)) .Select(path => { var fileInfo = new FileInfo(path); var isDirectory = File.GetAttributes(path).HasFlag(FileAttributes.Directory); var parentId = Path.GetDirectoryName(path.Substring(rootPath.Length + 1)); return new { id = Path.Combine(parentId, Path.GetFileName(path)), parentId, name = Path.GetFileName(path), modifiedDate = fileInfo.LastWriteTime, createdDate = fileInfo.CreationTime, size = isDirectory ? (long?)null : fileInfo.Length, isDirectory, hasItems = isDirectory && Directory.EnumerateFileSystemEntries(path).Count() > 0 }; }) .Where(i => i.name != "bin" && i.name != "obj" && i.name != "packages" && i.name.Length > 0 && !i.name.StartsWith(".")) .OrderByDescending(i => i.isDirectory) .ThenBy(i => i.name); return Request.CreateResponse(childNodes); } } }
#treelist { max-height: 440px; }

This feature requires client- and server-side configurations. To configure the client-side part, do the following:

  1. Send an expanded node's ID to the server
    For this, implement the CustomStore's load function. In this demo, we do it in the dataSource configuration object.

  2. Delegate filtering to the server
    Set the remoteOperations.filtering property to true.

  3. Specify the data field that defines whether the node has children
    Use the hasItemsExpr property to set this data field.

Server-side implementation is available in the ASP.NET Core and ASP.NET MVC versions of this demo under the TreeListDataController.cs tab.

NOTE

This demo uses a simple data bind technique that is useful for data display purposes only. When a user clicks a node, TreeList receives a JSON object from the server, which is based on the parentIds property value. This technique does not support the built-in data process operations in TreeList on the server.

If your project needs to process data, do one of the following instead: