Ok, ladies and gents, I just couldn't take it any longer! The out of the box navigation for blogs is less than ideal and although I will be soon investigating different content query web parts to accomplish the same thing, I went ahead a build a new one. Essentially, I wanted a grouping of blog articles in some sort of tree view as a web part. Simple right? The answer to this is actually yes. What I will plan to do here is simply write a quick code base and deploy to my site. At that point, I can just add my web part and ta-da, workie workie.


  1. Create a CAML query based on the "Posts" list that just orders the posts by publish date. This will look something like:

using (SPWeb spWeb = SPContext.Current.Web)


string DocumentLib = "Posts";

string sUrl = spWeb.Url;

string PostDate = string.Empty;

SPList list = spWeb.Lists[DocumentLib];// here DocumentLib is name of the name of documentlibrary we are passing

SPQuery docQuery = new SPQuery();

docQuery.ViewFields = @"<FieldRef Name=""LinkTitle""/>";

docQuery.ViewFields += @"<FieldRef Name=""PublishedDate""/>";

string CamlQ =


<FieldRef Name=""PublishedDate"" Ascending=""False"" />


docQuery.Query = CamlQ;


  1. Loop through these posts creating a string representation of XML that looks something like:

sBlogs = @"<?xml version=""1.0"" encoding=""utf-8"" ?>";

sBlogs += @"<BlogPosts>";

SPListItemCollection docList = list.GetItems(docQuery);

foreach (SPListItem item in docList)


DateTime PublishedDate = DateTime.Parse(item["PublishedDate"].ToString());

if (PostDate != PublishedDate.ToString("MMMM yyyy"))


//Make sure not first time through loop

if (PostDate != string.Empty)


sBlogs += @"</PostMonth>";


PostDate = PublishedDate.ToString("MMMM yyyy");

sBlogs += @"<PostMonth name=""" + PostDate + @""">";


sBlogs += @"<PostName name=""" + item["LinkTitle"].ToString() + @""" url=""" + sUrl + @"/Lists/Posts/Post.aspx?ID=" + item.ID.ToString() + @"""/>";


sBlogs += @"</PostMonth>";

sBlogs += @"</BlogPosts>";


return sBlogs;



  1. Create an XML Data Source and attach your bindings accordingly

XmlDataSource xBlogPosts = new XmlDataSource();

xBlogPosts.EnableCaching = false;

XmlDocument xXMLDoc = new XmlDocument();

TreeNodeBinding tnbTop = new TreeNodeBinding();

TreeNodeBinding tnbMonth = new TreeNodeBinding();

TreeNodeBinding tnbName = new TreeNodeBinding();

string sXMLDoc = string.Empty;



if (!Page.IsPostBack)


//Create XML

sXMLDoc = GetBlogPosts();

//Load XML DataSource


xBlogPosts.Data = xXMLDoc.InnerXml;


  1. You will then set your XPath to narrow down your tree

xBlogPosts.XPath = "BlogPosts/PostMonth";


  1. Create a Treeview and set the XML Datasource be the binding

//Create TreeNode Bindings

tnbTop.DataMember = "BlogPosts";

tnbTop.Text = "Blog Posts";

tnbMonth.DataMember = "PostMonth";

tnbMonth.TextField = "name";

tnbName.DataMember = "PostName";

tnbName.TextField = "name";

tnbName.NavigateUrlField = "url";

//Associate TreeView Bindings








  1. Add the tree view through the RenderChildren method as explained in an earlier post here.



  1. Make sure you dispose your objects that you explicitly instantiate


xBlogPosts = null;

xXMLDoc = null;

tnbTop = null;

tnbMonth = null;

tnbName = null;


tv = null;


  1. Build and deploy your finished webpart
  2. Add the webpart to the page(s) in question


Finishing touches

For full sample of the code, simply email me or send comment. I have uploaded the cs file, however, anonymous access is not yet enabled. I was tired of writing the code in the blog all the time, so figured I would try a different approach this time.

The end product looks something like:



Pretty cool huh?