Click here to Skip to main content
14,111,188 members
Click here to Skip to main content
Add your own
alternative version

Stats

95.3K views
2.3K downloads
56 bookmarked
Posted 3 Apr 2019
Licenced CDDL

Dynamic Treeview with Drag and Drop by Kendo

, 4 Apr 2019
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 the 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 the 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 link 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, the 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 the above data model in step 3 which illustrates there are personnel in organization who may be have a manager or employer, if your database is different, then you should look at code and change that a little.

To generate hierarchical Data Source as JSON file, follow these 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)

whose output is json as string and get:

  1. itemID --> ID for current node
  2. mystr --> previous json string
  3. {in every self call this method, new string will be added to mystr}
  4. j is inner counter
  5. 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).

  1. Assume you do not know the current node, so itemid is equal to zero
  2. The first time, you do not have any string for json
  3. j = 0 as the same token
  4. flag = 0 as the same token

Step 3

Check whether this current node has parent or not ?

  1. Main node root: if you are, just enter this method, so assume you have to:
    • Select from data base
    • Nodes which have no parents and their parent id is equal to NULL
    • Here, generate your json string like **mystr = "["**
  2. Nested node: If this method has been called more than once, check all nodes:
    • where 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 the third step:

  1. Make a foreach loop and call each node and write it like
  2. foreach (item in querylist)
    **mystr = { id: "" , text: ""**
    
  3. Inside this loop, check whether this node has child or not?
    Querylist= select personal where reportsto=item.id
    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 as this node is parent and has child

    2. **(It has No Child && this node is not last node)**
      **mystr =" }, "**
    3. **(It has No Child && this node is last node)**
      1. Count number of parents of this node
        Foreach parent put **mystr = "}]"**
      2. Count number of child of parents of this node
        1. if (Child = 0) **mystr = "}]"**
        2. if (Child > 0) **mystr = "}]"**
          1. if (This node is the last child node && parent of this node is last parent)
            **mystr = "},"**
          2. if (This node is the last child node && parent of this node is last parent &&
            flag=1 )
            **mystr =" },"**
          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 getting 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.

1st 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 cannot make circle in treeview such as P1 is parent for P2 and also P2 is parent for P1 is incorrect and makes a 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
Doctorandin Technische Universität Berlin
Iran (Islamic Republic of) Iran (Islamic Republic of)
I have been working with different technologies and data more than 10 years.
I`d like to challenge with complex problem, then make it easy for using everyone. This is the best joy.

ICT Master in Norway 2013
Doctorandin at Technische Universität Berlin in Data Scientist ( currently )
-------------------------------------------------------------
Diamond is nothing except the pieces of the coal which have continued their activities finally they have become Diamond.

http://www.repocomp.com/

You may also be interested in...

Comments and Discussions

 
QuestionBroken Images Pin
.dan.g.3-Apr-19 22:58
professional.dan.g.3-Apr-19 22:58 
AnswerRe: Broken Images Pin
Mahsa Hassankashi4-Apr-19 12:35
memberMahsa Hassankashi4-Apr-19 12:35 
Questiondemo does not work in IE or Google Chrome Pin
cengen6-Oct-15 5:46
membercengen6-Oct-15 5:46 
AnswerRe: demo does not work in IE or Google Chrome Pin
Mahsa Hassankashi14-Aug-16 6:29
memberMahsa Hassankashi14-Aug-16 6:29 
GeneralMy vote of 5 Pin
Dariush Tasdighi8-Apr-15 20:32
memberDariush Tasdighi8-Apr-15 20:32 
GeneralRe: My vote of 5 Pin
Mahsa Hassankashi14-Aug-16 6:28
memberMahsa Hassankashi14-Aug-16 6:28 
GeneralMy vote of 5 Pin
Galadriel10926-Feb-15 8:24
memberGaladriel10926-Feb-15 8:24 
GeneralRe: My vote of 5 Pin
Mahsa Hassankashi3-Apr-15 20:53
memberMahsa Hassankashi3-Apr-15 20:53 
QuestionHow to implement with string IDs Pin
Galadriel10919-Feb-15 5:42
memberGaladriel10919-Feb-15 5:42 
AnswerRe: How to implement with string IDs Pin
Mahsa Hassankashi20-Feb-15 12:12
memberMahsa Hassankashi20-Feb-15 12:12 
GeneralRe: How to implement with string IDs Pin
Galadriel10923-Feb-15 7:00
memberGaladriel10923-Feb-15 7:00 
GeneralRe: How to implement with string IDs Pin
Mahsa Hassankashi23-Feb-15 14:04
memberMahsa Hassankashi23-Feb-15 14:04 
GeneralRe: How to implement with string IDs Pin
Galadriel10926-Feb-15 8:14
memberGaladriel10926-Feb-15 8:14 
GeneralRe: How to implement with string IDs Pin
Mahsa Hassankashi26-Feb-15 16:24
memberMahsa Hassankashi26-Feb-15 16:24 
GeneralMy vote of 5 Pin
Mihai MOGA13-Aug-14 3:14
professionalMihai MOGA13-Aug-14 3:14 
GeneralRe: My vote of 5 Pin
Mahsa Hassankashi13-Aug-14 3:53
memberMahsa Hassankashi13-Aug-14 3:53 
QuestionIt is nice to see a lady dev from Iran share a passion for development Pin
Member 1096926612-Aug-14 19:03
memberMember 1096926612-Aug-14 19:03 
AnswerRe: It is nice to see a lady dev from Iran share a passion for development Pin
Mahsa Hassankashi12-Aug-14 22:37
memberMahsa Hassankashi12-Aug-14 22:37 
AnswerRe: It is nice to see a lady dev from Iran share a passion for development Pin
Mahsa Hassankashi13-Aug-14 7:44
memberMahsa Hassankashi13-Aug-14 7:44 
Questionwonder full article Pin
Member 10419912-Aug-14 12:35
memberMember 10419912-Aug-14 12:35 
GeneralRe: wonder full article Pin
Mahsa Hassankashi12-Aug-14 22:33
memberMahsa Hassankashi12-Aug-14 22:33 
QuestionGreat Pin
Aldis Aldrichi12-Aug-14 5:15
memberAldis Aldrichi12-Aug-14 5:15 
AnswerRe: Great Pin
Mahsa Hassankashi12-Aug-14 22:34
memberMahsa Hassankashi12-Aug-14 22:34 
GeneralMy vote of 5 Pin
Renju Vinod10-Aug-14 19:43
professionalRenju Vinod10-Aug-14 19:43 
GeneralRe: My vote of 5 Pin
Mahsa Hassankashi10-Aug-14 23:55
memberMahsa Hassankashi10-Aug-14 23:55 

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

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

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web06 | 2.8.190518.1 | Last Updated 4 Apr 2019
Article Copyright 2019 by Mahsa Hassankashi
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid