How to load child node on expand kendo treeview

2.7k views Asked by At

I want to create a treeview with nodes from folders and files on my PC. User can drag and drop nodes.

My design view (cshtml) :

@(
    Html.Kendo().TreeView()
        .Name("treeview")
        .Events(ev=>ev.Expand("onExpand"))
        .BindTo((IEnumerable<TreeViewItemModel>)ViewBag.ParentNode)
)

My Controller :

public class HomeController : Controller
{
    public ActionResult TreeView()
    {
        ViewBag.ParentNode = GetDefaultNode();
        return View();
    }
    private IEnumerable<TreeViewItemModel> GetDefaultNode()
    {
        List<TreeViewItemModel> defaultNode = new List<TreeViewItemModel>();
        string[] drivers = Directory.GetLogicalDrives();
        for (int i = 0; i < drivers.Length; i++)
        {
                TreeViewItemModel node = new TreeViewItemModel();
                node.Text = drivers[i];
                node.Url = drivers[i];
                defaultNode.Add(node);
                GetChildNode(node);
        }

        return defaultNode;
    }
    private void GetChildNode(TreeViewItemModel item)
    {
        if (Directory.Exists(item.Text))
        {
            try
            {
                string[] dirNodes = Directory.GetDirectories(item.Text);
                if (dirNodes.Length > 0)
                {
                    for (int i = 0; i < dirNodes.Length; i++)
                    {
                        TreeViewItemModel child = new TreeViewItemModel();
                        DirectoryInfo dirInfo = new DirectoryInfo(dirNodes[i]);
                        child.Text = dirInfo.Name;
                        child.Url = dirInfo.FullName;
                        child.HasChildren = true;
                        item.Items.Add(child);
                        child.Items.Add(new TreeViewItemModel());
                    }
                }
                string[] fileNodes = Directory.GetFiles(item.Text);
                if (fileNodes.Length > 0)
                {
                    for (int f = 0; f < fileNodes.Length; f++)
                    {
                        TreeViewItemModel child = new TreeViewItemModel();
                        FileInfo fileInfo = new FileInfo(fileNodes[f]);
                        child.Text = fileInfo.Name;
                        child.Url = fileInfo.FullName;
                        child.HasChildren = true;
                        item.Items.Add(child);
                    }
                }

            }
            catch { }

        }
    }
}

It show root node and child of root node.

I want child nodes load on user expand root node. So I declare events onExpand in treeview, but I don't know how to pass a current expand node to controller, and get a list of nodes on view, after that insert it to current expand nodes. I had searched a lot on this page and google, but can't find the way to solve my problems.

ps:sorry because I'm not good in English, hope you can understand my mean.

Update:

I change to use Binding to remote date but i still have not solved my problems.

My cshtml:

    @(Html.Kendo().TreeView()
.Name("treeview")
.DataTextField("Text")
.DataUrlField("Url")
.DataSource(dataSource => dataSource
    .Read(read => read
        .Action("GetRoot", "Home")
    )
)
)

My controller:

        public JsonResult GetRoot()
    {
        return Json(GetDefaultNode(), JsonRequestBehavior.AllowGet);
    }
    private IEnumerable<TreeViewItemModel> GetDefaultNode()
    {
        List<TreeViewItemModel> defaultNode = new List<TreeViewItemModel>();
        string[] drivers = Directory.GetLogicalDrives();
        for (int i = 0; i < drivers.Length; i++)
        {
                TreeViewItemModel node = new TreeViewItemModel();
                node.Text = drivers[i];
                node.Url = drivers[i];
                defaultNode.Add(node);
                GetChildNode(node);
        }

        return defaultNode;
    }
    private void GetChildNode(TreeViewItemModel item)
    {
        if (Directory.Exists(item.Text))
        {
            try
            {
                string[] dirNodes = Directory.GetDirectories(item.Text);
                if (dirNodes.Length > 0)
                {
                    for (int i = 0; i < dirNodes.Length; i++)
                    {
                        TreeViewItemModel child = new TreeViewItemModel();
                        DirectoryInfo dirInfo = new DirectoryInfo(dirNodes[i]);
                        child.Text = dirInfo.Name;
                        child.Url = dirInfo.FullName;
                        item.Items.Add(child);
                    }
                }
                string[] fileNodes = Directory.GetFiles(item.Text);
                if (fileNodes.Length > 0)
                {
                    for (int f = 0; f < fileNodes.Length; f++)
                    {
                        TreeViewItemModel child = new TreeViewItemModel();
                        FileInfo fileInfo = new FileInfo(fileNodes[f]);
                        child.Text = fileInfo.Name;
                        child.Url = fileInfo.FullName;
                        item.Items.Add(child);
                    }
                }

            }
            catch { }

        }
    }

And this is result:

enter image description here

As you see, it only show root nodes without child nodes.When i debug, root nodes contain childs

enter image description here

1

There are 1 answers

0
Nguyễn Huy On BEST ANSWER

Problems solved. When using remote databinding, nodes only load on the same level.When onExpand fire, it will call method GetNodes again.

 public JsonResult GetNodes(string id)
    {
        List<Node> node = new List<Node>();
        List<string> drivers=new List<string>();
        if (string.IsNullOrEmpty(id))
        {
            drivers.AddRange(Directory.GetLogicalDrives());
        }
        else
        {
            if(Directory.Exists(id))
                drivers.AddRange(Directory.GetDirectories(id));
        }

            try
            {
                for (int i = 0; i < drivers.Count; i++)
                {
                    Node item = new Node();
                    DirectoryInfo dirInfo = new DirectoryInfo(drivers[i]);
                    item.id = dirInfo.FullName;
                    item.Name = dirInfo.Name;
                    item.hasChildren = HasNodes(drivers[i]);
                    node.Add(item);
                }
            }
            catch { }

        return Json(node, JsonRequestBehavior.AllowGet);
    }