This blog demonstrates how you can create folders on the server, and upload files to these folders using the C1Upload control. C1TreeView control is used to show the folder structure on the server and C1Upload control is used to upload files to these folders. User can create new folders, delete them, rename them and can upload files to these folders. Subfolders under existing folders can also be created and files can be uploaded to any of these folders by selecting it. All these features are implemented by using the client side functionality of C1TreeView to add/remove/rename nodes of the tree. Similarly, corresponding folders are created/deleted/renamed on the server using an ajax() call to the server. When the page loads, C1TreeView is populated with nodes based on the folder structure already present on the server. Following is the code implementation to populate C1TreeView.


public void InitializeTree(string parentFolder, C1TreeViewNode parentNode)  
{  
 foreach (string folderName in Directory.GetDirectories(Path.Combine(parentFolder, "")))  
  {  
     DirectoryInfo dir = new DirectoryInfo(folderName);  
     C1TreeViewNode node = new C1TreeViewNode();  
     node.Text = dir.Name;  
     node.CollapsedIconClass = "ui-icon-folder-collapsed";  
     node.ExpandedIconClass = "ui-icon-folder-expanded";  
     node.ItemIconClass = "ui-icon-document";  
     if (parentNode == null)  
        C1TreeView1.Nodes.Add(node);  
     else  
        parentNode.Nodes.Add(node);  
     if (dir.GetFiles().Length > 0)  
     {  
      foreach (FileInfo file in dir.GetFiles())  
      {  
       C1TreeViewNode filenode = new C1TreeViewNode();  
       filenode.Text = file.Name;  
       filenode.ItemIconClass = "ui-icon-file";  
       node.Nodes.Add(filenode);  
       }  
      }  
     if (dir.GetDirectories().Length > 0)  
      InitializeTree(dir.FullName, node);  
  }  
}  

File Manager uses the selectedNodeChanged event of C1TreeView to get the selected node. The path to be sent to the server is created in this event. Based on this path, folders are created, deleted, and renamed on the server. For client side functionality, we'll use the methods of C1TreeView. Following is the code implementation for "selectedNodeChanged" event:


//event to get variable "selectedpath", raised everytime a new node is selected  
selectedNodeChanged: function (e, data) {  
   //selected node's span element, used in btnRename event.  
   nodeElementSpan = data.$inner.find('span :eq(1)');  
   //calculate selected node's path  
   selectedPath = data._text;  
   var owner = $(data.element).c1treeviewnode('getOwner');  
   var currentLevel = 0;  
   if (owner == null) {  
     selectedPath = data._text;  
     currentLevel = 0;  
   }  
   else {  
      selectedPath = data._text;  
      currentLevel = $(data.element).c1treeviewnode('getOwner')._getCurrentLevel();  
      var node = $(data.element).c1treeviewnode('getOwner');  
      while (currentLevel >= 0) {  
       selectedPath = $($(node)[0].element).c1treeviewnode("option", "text") + "\\\\\\" + selectedPath;  
       node = $($(node)[0].element).c1treeviewnode('getOwner');  
       if (node == null)  
          break;  
       currentLevel--;  
      }  
    }  
},  

Following are the details on features implemented on client side. Add Root Node or Creating New Folder Add() method of C1TreeView is used to add a new root node to the tree. A new node with name "New Folder" is created. After this, an ajax() call is made to call a page method to create a new folder with name "New Folder" on server.



//add node to tree  

$("#C1TreeView1").c1treeview("add", "New Folder", 0);  
var nodes = $("#C1TreeView1").c1treeview("getNodes");  
//set new nodes peroperties  
 $(nodes[0].element).c1treeviewnode("option", {  
 collapsedIconClass: "ui-icon-folder-collapsed",  
 expandedIconClass: "ui-icon-folder-open",  
 itemIconClass: "ui-icon-document",  
 selected: true  
 });  
var folderName = selectedPath;  

Add Child Node or Creating a Subfolder In this method, a node is selected and add() method is used to create a child node to the selected node. Path of this new node is extracted in the "selectedNodeChanged" event of C1TreeView in a variable "selectedPath". It is checked if the selected node is a file or a folder. If it's a file, subfolder can't be created. If it's a folder, subfolder has to be created at 0th index. For this, the "selectedPath" is passed to the server side and a subfolder corresponding to this path is created.

selectedNode = $(selectedNodes[0].element);  
 selectedNode.c1treeviewnode("add", "New Folder", 0);  
 selectedNode.c1treeviewnode("option", {  
 expanded: true,  
 selected: false  
 });  

 var childNodes = selectedNode.c1treeviewnode("getNodes");  
 //set properties of child node  
 $(childNodes[0].element).c1treeviewnode("option", {  
 collapsedIconClass: "ui-icon-folder-collapsed",  
 expandedIconClass: "ui-icon-folder-open",  
 itemIconClass: "ui-icon-document",  
 selected: true  
 });  

 //get path of child node to pass to server  
 var path = selectedPath;  

Deleting a Node or Deleting a Folder/File In this method it is checked if the node is a root node or child node. If it's a root node, it's deleted using the "remove" method of C1TreeView by passing the node's index. If selected node is a child of a node, remove method of its parent node is called to remove the node. Selected node's path is passed to the server to delete the folder and all of its sub folders and files.

//get selected node to delete  
 var selectedNodes = $("#C1TreeView1").c1treeview("getSelectedNodes");  

 //if a node is selected, delete it.  
 if (selectedNodes.length > 0) {  
      var text = $(selectedNodes[0].element).c1treeviewnode("option", "text");  
      //get owner of node to be deleted.  
      var owner = $(selectedNodes[0].element).c1treeviewnode("getOwner");  

      if (owner != null) {  
        //get index based on ownwer node if node is not a root node  
        var nodes = owner.getNodes();  
        $(nodes).each(function (index, element) {  
        if ($(this)[0]._text == text) {  
           $(owner)[0].remove(index);  
       }  
 });  
 }  
 else {  
     //get index if node is a root node of the tree  
     var nodes = $("#C1TreeView1").c1treeview("getNodes");  
     $(nodes).each(function (index, element) {  
     if ($(this)[0]._text == text) {  
       $("#C1TreeView1").c1treeview("remove", index);  
     }  
 });  
}  
//get Selected Node's path  
var path = selectedPath;

Renaming a Node To rename a node, the click event of the node's "span" tag needs to be handled.

$("#btnRename").click(function () {  
   if ($(nodeElementSpan).length == 0) {  
     alert("Select a Folder or File to rename.");  
   }  
   else {  
     $(nodeElementSpan).click();  
   }  
  return false;  
});

When user changes the text of the node, "nodeTextChanged" event of the selected node is raised. If text is changed, new text of the node is passed to server side for renaming the file/folder at server side.



//event to handle renaming a node.  
 nodeTextChanged: function (e, data) {  
    //check if node text has been changed  
    if (data._text != data.options.text) {  
      //get new name  
      var newFolderName = data.options.text;  
      //get path of child node to pass to server  
      var owner = $(data.element).c1treeviewnode('getOwner');  
      var currentLevel = 0;  
      if (owner == null) {  
        pathOfNode = data._text;  
        currentLevel = 0;  
      }  
      else {  
        pathOfNode = data._text;  
        currentLevel = $(data.element).c1treeviewnode('getOwner')._getCurrentLevel();  
        var node = $(data.element).c1treeviewnode('getOwner');  
        while (currentLevel >= 0) {  
            pathOfNode = $($(node)[0].element).c1treeviewnode("option", "text") + "\\\\\\" + pathOfNode;  
            node = $($(node)[0].element).c1treeviewnode('getOwner');  
            if (node == null)  
              break;  
           currentLevel--;  
     }  
}

Uploading a File C1Upload control is used to upload files to the specified location on the server. A new node is created for the file in the "upload" event of C1Upload. Path of this file has to be passed to the server side event OnValidatingFile of C1Upload. The "SaveAs" method of this event is used to upload file to the path passed from client side.

//1. upload event is raised once the upload button of a file is clicked.  
 upload: function (e, data) {  
 var filename = data[0].value;  
 var arr = filename.split("\\\");  
 filename = arr[arr.length - 1];  
 var selectedNodes = $("#C1TreeView1").c1treeview("getSelectedNodes");  
 if (selectedNodes.length > 0) {  
     //check if selected node is a file or a folder  
     var ele = selectedPath.split("\\\").pop();  
     if (ele.split(".").length > 1) {  
       if (flagUploadAll == true) {  
         flagUploadAll = false;  
       }  
       else {  
        alert("this is a file, can't upload file under it.");  
       }  
     }  
     //if selected node is a folder  
     else {  
       $(selectedNodes[0].element).c1treeviewnode("add", filename, 0);  
       $(selectedNodes[0].element).c1treeviewnode("option", { expanded: true, selected: false });  
       var childNodes = $(selectedNodes[0].element).c1treeviewnode("getNodes");  
       $(childNodes[0].element).c1treeviewnode("option", {  
       itemIconClass: "ui-icon-document",  
       selected: true  
     });  
     var path = selectedPath;  
     CallTheServer(path, '');   //2. Server side RaiseCallbackEvent method is called  
    }  
 }  
 else {  
    alert("Select the target folder..!!");  
 }  
}

As OnValidatingFile event is a callback event, we have used a Page.RegisterClientScriptBlock to pass value to server side from client side. On the server side ICallbackEventHandler interface is implemented and in the method RaiseCallbackEvent value passed from client side is saved in a Session Variable. This session variable is then saved in the current context with the help of a handler "Handler.ashx" and retrieved in the OnValidatingFile event as follows:

protected void C1Upload1_ValidatingFile(object sender, C1.Web.Wijmo.Controls.C1Upload.ValidateFileEventArgs e)  
{  
   string path = Path.Combine(Server.MapPath("~/TargetFolder"),     HttpContext.Current.Session["path"].ToString());  

  while (File.Exists(path))  
  {  
    string filename = HttpContext.Current.Session["path"].ToString();  
    path = Server.MapPath("~/TargetFolder") + "\\\" + filename.Split('.')[0] + uploadedFileCount + "." +    filename.Split('.')[1];  
   uploadedFileCount++;  
  }  
  e.UploadedFile.SaveAs(path);  

  e.IsValid = false;  
}  

Following screenshot shows an implementation of the File Manager using C1TreeView and C1Upload. Download Sample for complete implementation.