Tuesday, February 9, 2010

List Tree View in Sharepoint


In one of our project there are more than 100 lists and every list is having nested folders as well as many items. My client don't want to dig the list to see all the nested folder inside it. So we decided to provide him the Tree View control which will show all the lists inside site and also show all the items/data inside a list and he can easily navigate to particular list/folder and item.

First we will show all the items/nested folder in TreeView

using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Collections.Generic;
using System.Text;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;

namespace Nishnat.ListTreeView
{
public class ListItems : WebControl
{
public string ListName { get; set; }

protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)
{
// render the control
base.RenderContents(writer);
}

protected override void CreateChildControls()
{
base.CreateChildControls();

using (SPSite ospSite = new SPSite("http://localhost:7777/"))
{
using (SPWeb web = ospSite.RootWeb)
{
try
{
SPList list = web.Lists[ListName];

SPFolder rootFolder = list.RootFolder;
TreeView listTree = new TreeView();
listTree.ShowLines = true;
listTree.ExpandDepth = 0;

TreeNode rootNode = new TreeNode();

//Bind tree
MakeTreee(rootFolder, rootNode);

// add the root node to tree view
listTree.Nodes.Add(rootNode);
this.Controls.Add(listTree);
}
catch(Exception ex)
{
throw ex;
}
}
}
}

private void MakeTreee(SPFolder rootFolder, TreeNode rootNode)
{
SPQuery query = new SPQuery();
query.Folder = rootFolder;
SPWeb web = rootFolder.ParentWeb;
SPListItemCollection listColl = web.Lists[rootFolder.ParentListId].GetItems(query);

foreach (SPListItem subitem in listColl)
{
if (subitem.Folder != null) //Is folder
{
TreeNode childNode = new TreeNode(subitem.Folder.Name,subitem.ID.ToString(), "_layouts/images/folder.gif", subitem.Folder.ServerRelativeUrl, "");
rootNode.ChildNodes.Add(childNode);
MakeTreee(subitem.Folder, childNode);
}
else
{
string displayURL = GetDisplayUrl(subitem);

TreeNode childNode = new TreeNode(subitem.Name, subitem.Name, "", displayURL, "");
rootNode.ChildNodes.Add(childNode);
}
}
}

private static string GetDisplayUrl(SPListItem item)
{
SPList list = item.ParentList;
SPWeb web = list.ParentWeb;

string dispUrl = item.ContentType.DisplayFormUrl;
//dispUrl = String.Format("{0}/{1}?ID={2}", web, dispUrl, item.ID);

if (dispUrl == "")
dispUrl = list.Forms[PAGETYPE.PAGE_DISPLAYFORM].Url;

bool isLayouts = dispUrl.StartsWith("_layouts/", StringComparison.CurrentCultureIgnoreCase);
dispUrl = String.Format("{0}/{1}?ID={2}", web, dispUrl, item.ID);

if (isLayouts)
dispUrl = String.Format("{0}&List={1}", dispUrl, SPEncode.UrlEncode(list.ID + ""));
return dispUrl;
}
}
}


Second we will show all the Lists/items/nested folder in TreeView


using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Collections.Generic;
using System.Text;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;

namespace Nishnat.ListTreeView
{
public class AllListsWithItems : WebControl
{
protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)
{
// render the control
base.RenderContents(writer);
}

protected override void CreateChildControls()
{
base.CreateChildControls();

using (SPSite ospSite = new SPSite("http://localhost:7777/"))
{
using (SPWeb web = ospSite.RootWeb)
{
try
{
TreeView listTree = new TreeView();
listTree.ShowLines = true;
listTree.ExpandDepth = 0;

SPListCollection listAll = web.Lists;

foreach (SPList list in listAll)
{
SPFolder rootFolder = list.RootFolder;

TreeNode rootNode = new TreeNode(list.Title,list.ID.ToString(),list.ImageUrl,list.ParentWebUrl,"");

//Bind tree
MakeTreee(rootFolder, rootNode);

// add the root node to tree view
listTree.Nodes.Add(rootNode);
this.Controls.Add(listTree);
}
}
catch(Exception ex)
{
throw ex;
}
}
}
}

private void MakeTreee(SPFolder rootFolder, TreeNode rootNode)
{
SPQuery query = new SPQuery();
query.Folder = rootFolder;
SPWeb web = rootFolder.ParentWeb;
SPListItemCollection listColl = web.Lists[rootFolder.ParentListId].GetItems(query);

foreach (SPListItem subitem in listColl)
{
if (subitem.Folder != null) //Is folder
{
TreeNode childNode = new TreeNode(subitem.Folder.Name,subitem.ID.ToString(), "_layouts/images/folder.gif", subitem.Folder.ServerRelativeUrl, "");
rootNode.ChildNodes.Add(childNode);
MakeTreee(subitem.Folder, childNode);
}
else
{
string displayURL = GetDisplayUrl(subitem);

TreeNode childNode = new TreeNode(subitem.Name, subitem.Name, "", displayURL, "");
rootNode.ChildNodes.Add(childNode);
}
}
}

private static string GetDisplayUrl(SPListItem item)
{
SPList list = item.ParentList;
SPWeb web = list.ParentWeb;

string dispUrl = item.ContentType.DisplayFormUrl;
//dispUrl = String.Format("{0}/{1}?ID={2}", web, dispUrl, item.ID);

if (dispUrl == "")
dispUrl = list.Forms[PAGETYPE.PAGE_DISPLAYFORM].Url;

bool isLayouts = dispUrl.StartsWith("_layouts/", StringComparison.CurrentCultureIgnoreCase);
dispUrl = String.Format("{0}/{1}?ID={2}", web, dispUrl, item.ID);

if (isLayouts)
dispUrl = String.Format("{0}&List={1}", dispUrl, SPEncode.UrlEncode(list.ID + ""));
return dispUrl;
}
}
}


* Add assembly into GAC and Bin application

* Register the control on the page


<@ Register Tagprefix="Nishnat" Namespace="Nishnat.ListTreeView" Assembly="Nishnat.ListTreeView, Version=1.0.0.0, Culture=neutral, PublicKeyToken=57c7737278844f55">


* Now Use it on the page

<Nishnat:ListItems Id="listItems" runat="server" ListName="Books">
</Nishnat:ListItems>
<Nishnat:AllListsWithItems Id="AllListsWithItems" runat="server">
</Nishnat:AllListsWithItems>

9 comments:

  1. Hi
    Is it possible to concatenate ID with folder names to display in tree view sharepoint.

    Regards

    George

    ReplyDelete
  2. I had not tried that, because our interest only in displaying particular item's details on display form.

    ReplyDelete
  3. Hi

    Thank you for this I was looking for Custom Tree View and you made it ! But I have some issues to personalize it, what kind of Lists do you use ? I tried a Link List but I can't organize it with Folders like your first image, can you explain how did you do that please ?

    Thank you so much

    Chris

    ReplyDelete
  4. Oh my mistake I just found out how tu create folders on the list, but can I ask you how to create wiki pages and make them appear dynamically in a links list without touching anything ?

    ReplyDelete
  5. Chris
    It's not easy as you think. In this case you have to make one custom event reciever and attach it to the wiki page library. Event reciever will put newly created page url (absolute url probably) and title in links list. Go through this article for event reciever http://msdn.microsoft.com/en-us/library/ff713708(v=office.12).aspx

    ReplyDelete
  6. Appareciate your efforts. Please dont take this as a criticism. imo, its bad programming. What if,

    1. if the list has 5000 items (this is a huge perf hit)
    2. It should pick up the site its risiding (shouldn't be hard-coded or inputed like the above).
    3. Thirdly, placing this in a webpart might not be a idle solution but it has to be placed at the left tree view control (by Enhancing sharepoint OOTB treeview control)

    ReplyDelete
  7. Hi Sandip,

    I have a custom list with two folder content type.Based on content type, i have populated list item in a treeview.Dynamically i want to add subchild in selected node/subnode.How can I achieve this.Any idea plz.

    ReplyDelete
  8. @Dharma,

    You can do this as below,

    If possible write onclick event on node/subnode, based on that click open textbox like control to fill data by user, take reference of node/subnode id and add new item under that node/subnode(folder) and after adding refresh tree control to show newly added node.

    ReplyDelete
  9. Hi friend,
    I am doing this type of task only. I this same I bind the item from list to tree view. But I need to click that item in tree means it must be retrieve information from the list and it can be displayed into some control like textbox or label.

    ReplyDelete