Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Simple FileManager width MVC 3 and jsTree

0.00/5 (No votes)
2 Apr 2011 1  
In this article, I will show how easy it is to perform drag-and-drop and create operations using jsTree in a simple File Manager.

Introduction

I’ve seen several good tutorials on the net about jsTree and MVC, but they’re all somehow outdated and don’t work with jsTree’s latest version (which is a free component). It’s been a long time since I wanted to post the experience I had using jsTree (for those who don’t know what jsTree is, please go here: www.jstree.com). And what’s better to get it working than making a simple “File Manager”?

In this article, I will focus on two aspects of jsTree. The first that really blew me out was the possibility of moving trees by drag and drop, like in Windows Explorer (see Picture 1). The other feature I won’t cover (but is in the code) is using the right mouse button to display a context menu and from there create directories, rename, etc. I will not post a complete solution with rename, cut & copy features in this article, because it is just intended to be a starting point on how to use jQuery and MVC.

Picture 1: Drag and Drop

Using the code

First, we have to define our trees as JSON classes with a particular format:

public class JsTreeModel
{
    public string data;
    public JsTreeAttribute attr;
    public string state = "open";
    public List<JsTreeModel> children;
}

public class JsTreeAttribute
{
    public string id;
}

So in the data attribute, we’ll store the tree’s title, and the complete path will be stored in the ID attribute. The state of the tree will have all child leaves expanded by default, that’s what “open” is for.

We will use recursion to populate our tree, nothing really complicated.

Binding the tree

We have to use the following JavaScript to bind the tree using jQuery:

$('#MainTree').jstree({
            "json_data": {
                "ajax": {
                    "url": "/Home/GetTreeData",
                    "type": "POST",
                    "dataType": "json",
                    "contentType": "application/json charset=utf-8"
                 }
            },
            "themes": {
                "theme": "default",
                "dots": false,
                "icons": true,
                "url": "/content/themes/default/style.css"
            },

            "plugins": ["themes", "json_data", "dnd", "contextmenu", "ui", "crrm"]

        });

As you may have already understood, the “dnd” plugin stands for “Drag and Drop”.

And then the following syntax to perform the drag and drop operations:

$('#MainTree').bind("move_node.jstree", function (e, data) {
        data.rslt.o.each(function (i) {
            $.ajax({
                async: false,
                type: 'POST',
                url: "/Home/MoveData",
                data: {
                    "path": $(this).attr("id"),
                    "destination": data.rslt.np.attr("id")
                },
                success: function (r) {
                   Refresh();
                }
            });
        });
    });

On the controller side, we have to use:

[HttpPost]
public ActionResult MoveData(string path, string destination)
{
   // get the file attributes for file or directory
    FileAttributes attPath = System.IO.File.GetAttributes(path);

    FileAttributes attDestination = System.IO.File.GetAttributes(path);

    FileInfo fi = new FileInfo(path);

   //detect whether its a directory or file
   if ((attPath & FileAttributes.Directory) == FileAttributes.Directory)
    {
       if((attDestination & FileAttributes.Directory)==FileAttributes.Directory)
       {
           MoveDirectory(path, destination);
       }
    }
    else
    {
        System.IO.File.Move(path, destination + "\\" + fi.Name);
    }
    AlreadyPopulated = false;
    return null;   
}

I had to find another way to move a directory because Microsoft’s “Directory.Move” does not work in every case. Again, it’s just a starting point, it is not intended to be a complete solution.

Points of interest

One point that annoyed be a bit was the fact of having to refresh my tree in every task (move, create directory). It’s the only way I’ve found to keep sync the disk’s tree and the displayed one. Maybe some MVP could help me out if I just store the leaf’s name, I don’t know. I had to use a session state variable because otherwise if I click on the last leaf of the tree, I will have the entire tree populated again. And I couldn’t avoid it.

Anyway, I hope this article will help MVC developers wanting to use JSTree to improve the user’s experience and who don’t want to invest $500 in a professional component.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here