Click here to Skip to main content
Click here to Skip to main content
Go to top

Dynamic Treeview with Drag and Drop by Kendo

, 22 Aug 2014
Rate this:
Please Sign up or sign in to vote.
This article explains how to make data source for kendoTreeView, particularly it is designed for organization chart such as personals or documents which need nested query, after drag and drop one node to another one it will save it. Look at Demo

Introduction

Dynamic treeview with drag and drop is useful whenever you need to arrange employer or documents according to particular nested hierarchy. Assume one personnel in organization should report his or her tasks to upper manager and this manager has another upper manager and so on. In the other example, you want to arrange documents and define their parents such as { Finance -->Salary -->Personal} or { office -->letter -->import }. Kendoui treeview has the ability for drag and drop but in their example they used static string in json format such as [{ id: "1", text: "P1", items: [{ id: "5", text: "P2"}] }] that you should pass this string to kendo treeview data source. I write a method to generate these json to pass data source and after you change node location (parent), it will be saved.

Background

Firstly, you need to add some CSS and JS file from kendoui treeview to your project.

For more information about kendo UI treeview, look at the below links to know about binding local data and its structure:

Using this Code

Given below is a brief description of how I create a method to generate json format.

Step 1: Database

Firstly create a database and then table as personal:

Step 1.1: Table

Then fill this table:

Step 2: Data Model

Then make Entity Data Model (fast and easy):

Step 3: Model Class Inside Model Folder

This code is written in MVC so the below section is located in Model folder from table.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Treeview.Models
{
    public class Personal
    {
        public int ID { get; set; }
        public int Parent_ID { get; set; }
        public string Name { get; set; }
       
    }
}

Step 4: Main Method Inside Controller Folder

I have created "PersonalController.cs" inside controllers folder as follows:

Actually below logic description will generate self reference table as JSON format and then it passes its content to treeview data source.

I have generated this method for above data model in step 3 which illustrates there are personals in organization who maybe has manager or employer, if your data base is difference you should look at code and change a little on that.

 

To generate hierarchical Data Source as JSON file follow this steps and for full explanation follow the link:

 step 1: make a **nested** method so called Treeview

  public string Treeview(int itemID, string mystr, int j, int flag)

 which its output is json as string and get

 

      1.1: itemID -->  ID for current node

      1.2: mystr  --> previous json string

           {in every self call this method , new string will be added to mystr}

      1.3: j is inner counter

      1.4: flag is illustrated if current node has child or not

 

 step 2: First one you call this method from your action in mvc or other part of your  application call like that      Treeview(0,””,0,0) 

 

      2.1: Assume you do not know the current node so itemid is equal to zero

      2.2: At first time you do not have any string for json

      2.3: j = 0     as the same token

      2.4: flag = 0  as the same token

 

 step 3: Check this current node has parent or not ?

      3.1: Main node root: if you are just enter to this method so assume you have to  

           select from data base

           nodes which has no parents and their parent id is equal to NULL

           here generate your json string like **mystr = "["**

      3.2 Nested node : if this method has been called for more than once check all node

          which their parent is equal to itemid

          here generate your json string like **mystr = ",item:["**

 

 step 4: Now you have a list of data which you have tried from third step

      4.1: Make a foreach loop and call each node and write it like

      4.2:  foreach (item in querylist)

                 **mystr = { id: “” , text: “”**

         

      4.3: Inside this loop check this node has child or not?

            Querylist= select personal where reportsto=item.id 

         

        4.3.1: **(It has child)** --> call again Treeview method such as

               mystr = Treeview (item.id, mystr, i,1)  

              Now your item.id is crrent node, mystr is the whole string which is generated

              until now i as j and flag is equal to one due to this node is parent and

              has child

 

       4.3.2: **(It has No Child && this node is not last node)**

              **mystr =" }, "**

 

       4.3.3: **(It has No Child && this node is last node)**

           

              4.3.3.1: Count number of parent of this node

              Foreach parent put **mystr = "}]"**

             

              4.3.3.2: Count number  of child of parent of this node

       

                      4.3.3.2.1: if (Child = 0) **mystr =  "}]"**

                      4.3.3.2.2: if (Child > 0) **mystr =  "}]"**

 

                                4.3.3.2.2.1: if (This node is the last child node

                                            && parent of  this node is last parent) 

                                             **mystr = "},"**

 

                                4.3.3.2.2.2: if (This node is the last child node &&

                                                 parent of this node is last parent &&

                                                 flag=1 )

                                              **mystr =" },"**

 

                                4.3.3.2.2.3: if (This node is the last child node &&

                                                 parent of this node is last parent && 

                                                 flag=0 )

                                              **mystr =" }]"**

 

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;
using System.Diagnostics;
using System.Text;

namespace Treeview.Controllers
{
    public class PersonalController : Controller
    { 
        int mainNode = 0;
        int childquantity = 0;
        int myflag;

  [HttpPost]
        public ActionResult SaveNode(string childid, string parentid)
        {
            //*****REVISION******Do not allow reportsto = itself 
            if (childid != null && parentid != null && parentid != childid  )
            {
                string source = childid;
                string destination = parentid;
                using (var ctx = new TreeviewEntities())
                {
                    var personals = ctx.Personals.Where(m => m.Name == source).First();

                   var personalsParent = ctx.Personals.Where(m => m.Name ==  destination).First();

                    //***check
                   //*****REVISION******Do not allow make circle in data base such as P1 is parent for P2 and also P2 is parent for P1 ==> Prevent these mistake by checking it
                    //
           
                    if (personalsParent.ReportsTo!=personals.ID)
                    {
                        personals.ReportsTo = Convert.ToInt16(personalsParent.ID);


                        ctx.SaveChanges();
                    }
                    //***check

                    
                }
                
            }
            return RedirectToAction("Index");
        }



        public string Treeview(int itemID, string mystr, int j, int flag)
        {           
            List<Personal> querylist = new List<Personal>();
            var ctx = new TreeviewEntities();
            
            if (flag==0)
            {
               
               querylist = (from m in ctx.Personals
                             where m.ReportsTo == null
                             select m).ToList();
               mainNode = querylist.Count;
              
                mystr += "[";
            }
            if (flag == 1)
            {

                querylist = (from m in ctx.Personals
                             where m.ReportsTo == itemID
                             select m).ToList();
                mainNode = querylist.Count;
                mystr += ",items:[";
            }
            
            //Below line shows an example of how to make parent node with his child
            //[{ id: "1", text: "P1", items: [{ id: "5", text: "P2" }] }]

           int i=1;
                foreach (var item in querylist)
                {
                            myflag = 0;
                            mystr += "{id:\"" + item.ID + 
                            "\",text:\"" + item.Name + "\"";
                            List<Personal> querylistParent = new List<Personal>();
                            //Check this parent has child or not , if yes how many?
                            querylistParent = (from m in ctx.Personals
                                           where m.ReportsTo == item.ID
                                           select m).ToList();
                            childquantity = querylistParent.Count;
                            //If Parent Has Child again call Treeview with new parameter
                            if (childquantity > 0)
                            {
                                mystr = Treeview(item.ID, mystr, i, 1);
                              
                            }
                            //No Child and No Last Node
                            else if (childquantity == 0 && i < querylist.Count)
                            {
                                mystr += "},";
                            }
                            //No Child and Last Node
                            else if (childquantity == 0 && i == querylist.Count)
                            {                               
                               int fcheck2=0;
                               int fcheck3 = 0;
                               int counter = 0;
                               int flagbreak = 0;

                                int currentparent;
                                List<Personal> parentquery ;
                                List<Personal> childlistquery;
                                TempData["counter"] =0;
                                currentparent = Convert.ToInt16(item.ReportsTo);
                                int coun;
                                while (currentparent != 0)
                                {
                                    //count parent of parent
                                   
                                     fcheck2 = 0;
                                     fcheck3 = 0;
                                     parentquery = new List<Personal>();
                                     parentquery = (from m in ctx.Personals
                                                      where m.ID == currentparent
                                                      select m).ToList();
                                     var rep2 = (from h in parentquery 
                                     select new { h.ReportsTo }).First();
                                   
                                    //put {[ up to end
                                    
                                    //list of child
                                     childlistquery = new List<Personal>();
                                     childlistquery = (from m in ctx.Personals
                                                      where m.ReportsTo == currentparent
                                                     select m).ToList();

                                     foreach (var item22 in childlistquery)
                                        {                                           
                                            if (mystr.Contains(item22.ID.ToString()))
                                            {

                                                if (item22.ReportsTo == currentparent)
                                                {
                                                    fcheck3 += 1;
                                                    if (fcheck3 == 1)
                                                    {
                                                        counter += 1;
                                                    }
                                                }
                                            }
                                            else
                                            {                                               
                                                myflag = 1;
                                                if (item22.ReportsTo == currentparent)
                                                {
                                                     fcheck2+=1;
                                                     if (fcheck2==1)
                                                     {
                                                         counter -= 1;
                                                         flagbreak = 1;                                                         
                                                     }
                                                }                                                                                                                                             
                                            }
                                        }

                                     var result55 = 
                                     (from h in parentquery select new { h.ID }).First();
                                        coun = Convert.ToInt16(result55.ID);
                                        TempData["coun"] = Convert.ToInt16(coun);
                                        currentparent = Convert.ToInt16(rep2.ReportsTo);
                                        if (flagbreak == 1)
                                        {
                                            break;
                                        }                                       
                                }
                              
                                for (int i2 = 0; i2 < counter; i2++)
                                {
                                    mystr += "}]";
                                }

                                List<Personal> lastchild = new List<Personal>();
                                lastchild = (from m in ctx.Personals
                                                where m.ReportsTo == item.ReportsTo
                                                select m).ToList();

                                List<Personal> lastparent = new List<Personal>();
                                lastparent = (from m in ctx.Personals
                                                where m.ReportsTo == null
                                                select m).ToList();

                                if (lastchild.Count > 0)
                                {
                                    var result_lastchild = 
                                    (from h in lastchild select new { h.ID }).Last();
                                    var result_lastparent = 
                                    (from h in lastparent select new { h.ID }).Last();
                                    int mycount = Convert.ToInt16(TempData["coun"]);
                                    if (item.ID == result_lastchild.ID && 
                                    mycount == result_lastparent.ID && myflag == 0)
                                    {
                                       mystr += "}]";
                                    }
                                    else if (item.ID == result_lastchild.ID && 
                                    mycount == result_lastparent.ID && myflag == 1)
                                    {
                                       mystr += "},";
                                    }
                                    else if (item.ID == result_lastchild.ID && 
                                    mycount != result_lastparent.ID)
                                    {
                                       mystr += "},";
                                    }                                    
                                }
                                //  finish }]
                                else if (lastchild.Count == 0 && item.ReportsTo == null)
                                {
                                   mystr += "}]";
                                }
                            }
                            i++;   
                    }                    
            
            return mystr;
        }
       
        public ActionResult Index()
        {           
            ViewData["treeviewds"] = Treeview(0, "", 0, 0);
            return View();           
        }         
    }    
}

Step 5: UI Inside View

Then I have created "Index.cshtml" inside Views -->Personal folder as follows.

Step 5.1: Head

In the head section, you should define CSS and JS files:

Step 5.2: Body

Then make treeview div for appending json string to it and tvformat to pass viewdata["treeviewds"]:

Step 5.3: Script

Then write script for get treeview data from database and post (save) node which has been changed their parents (location):

Step 5.4: CSS

Then make style for it.

History

30th July 2014:

I have added demo link to this article

1th August 2014:

I have corrected two bugs in this article, first one if you click one node and then drop it to itself in SaveNode action I have edited it if parentid == childid so do not do anything

the second one is you can not make circle in treeview such as P1 is parent for P2 and also P2 is parent for P1 is incorrect and make circle

Feedback

Feel free to leave any feedback on this article; it is a pleasure to see your comments and vote about this code. If you have any questions, please do not hesitate to ask me here.

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)

Share

About the Author

Mahsa Hassankashi
Software Developer
Iran (Islamic Republic Of) Iran (Islamic Republic Of)
I have been working with .Net framework for 7 years.
I`d like to challenge with complex problem, then make it easy for using everyone. This is the best joy.
 
ICT Master student at University of Agder
-------------------------------------------------------------
Diamond is nothing except the pieces of the coal which have continued their activities finally they have become Diamond.
 
http://www.cosmicverse.info/
http://www.technical.cosmicverse.info
Follow on   Google+   LinkedIn

Comments and Discussions

 
GeneralMy vote of 5 PinprofessionalMihai MOGA13-Aug-14 3:14 
GeneralRe: My vote of 5 PinmemberMahsa Hassankashi13-Aug-14 3:53 
QuestionIt is nice to see a lady dev from Iran share a passion for development PinmemberMember 1096926612-Aug-14 19:03 
AnswerRe: It is nice to see a lady dev from Iran share a passion for development PinmemberMahsa Hassankashi12-Aug-14 22:37 
AnswerRe: It is nice to see a lady dev from Iran share a passion for development PinmemberMahsa Hassankashi13-Aug-14 7:44 
Questionwonder full article PinmemberMember 10419912-Aug-14 12:35 
GeneralRe: wonder full article PinmemberMahsa Hassankashi12-Aug-14 22:33 
QuestionGreat PinmemberAldis Aldrichi12-Aug-14 5:15 
AnswerRe: Great PinmemberMahsa Hassankashi12-Aug-14 22:34 
GeneralMy vote of 5 PinprofessionalRenju Vinod10-Aug-14 19:43 
GeneralRe: My vote of 5 PinmemberMahsa Hassankashi10-Aug-14 23:55 
QuestionDynamic Treeview with Drag and Drop by Kendo PinmemberMember 109112594-Aug-14 11:38 
AnswerRe: Dynamic Treeview with Drag and Drop by Kendo PinmemberMahsa Hassankashi6-Aug-14 1:38 
GeneralMy vote of 5 PinprofessionalSanjay K. Gupta31-Jul-14 19:02 
GeneralRe: My vote of 5 PinmemberMahsa Hassankashi31-Jul-14 20:52 
QuestionExcellent Article! PinmemberRene Pilon31-Jul-14 4:35 
AnswerRe: Excellent Article! PinmemberMahsa Hassankashi31-Jul-14 5:48 
QuestionVery nice Pinmemberbispenho30-Jul-14 15:13 
AnswerRe: Very nice PinmemberMahsa Hassankashi30-Jul-14 18:11 
QuestionGood Article PinmemberGihan Liyanage29-Jul-14 23:22 
AnswerRe: Good Article PinmemberMahsa Hassankashi30-Jul-14 1:43 
Generaluseful PinmemberFoad234523-Jul-14 9:59 
GeneralRe: useful PinmemberMahsa Hassankashi30-Jul-14 1:42 
Questionhello below are link can you join me in linkedin PinmemberArjunwalmiki23-Jul-14 8:29 
AnswerRe: hello below are link can you join me in linkedin PinmemberMahsa Hassankashi23-Jul-14 8:38 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140916.1 | Last Updated 22 Aug 2014
Article Copyright 2014 by Mahsa Hassankashi
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid