+1-888-365-2779
Try Now
More in this section
Categories
Bloggers
Blogs RSS feed

Filter CategoriesTree control by Blog.

by Ivan Dimitrov
The main reason of this post is a discussion that I had in Sitefinity's forum post. So, the problem here is that you have BlogPosts control that supports filtering , but the same does not apply for CategoriesTree control. Using BlogPosts FilterExpression property you can  show only a specific blog posts or group of blog posts instead of all blogs and posts from your provider. So far so good. The main problem comes here. When you drop CategoriesTree built-in control on a page and set ProviderName property, the CategoriesTree control is bound to all categories for this provider instead of categories related to your filtered list of blogs only. I managed to come up with a simple solution that requires creating a custom control that derives from CategoriesTree, implementing a simple property and overriding one method - BindCategories.

 

1. The property - I will implement a simple property of type Guid[] which will be used to return the ID of selected blogs. These blogs should be the same as those one listed in BlogPosts control

 

 [Category("FilterByCategories")] 
    [TypeConverter("Telerik.Blogs.WebControls.SelectedBlogsConverter, Telerik.Blogs")] 
    [WebEditor("Telerik.Blogs.WebControls.BlogsSelector, Telerik.Blogs")] 
    public Guid[] SelectedBlogs 
    { 
        get 
        { 
            return this.selectedBlogs; 
        } 
        set 
        { 
            this.selectedBlogs = value; 
        } 
    } 

2. Override LayoutTemplatePath property - we will "map" the external template for CategoriesTree which will allow to make some modifications in RadTreeView declaration.

   public override string LayoutTemplatePath 
    { 
        get 
        { 
            return "~/Sitefinity/ControlTemplates/Generic_Content/CategoriesTree.ascx"
        } 
    } 
 

3. Override BindCategories() method.

- here I check wether there is a value set for our property  SelectedBlog.  If there is no value I call the base and do not change anything. If there is a value set, I proceed with our custom logic.

- Get the blogs by IDs.

- Get all posts from our blogs

- get metadata - Category for IContent object

- create a new generic list of type ICategory

- add all matches to this list

- bind RadTreeView control to our custom list

- subscribe for NodeDataBound of RadTreeView contorl to set the node.NavigateUrl property.

 

The full code is shown below:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using Telerik.Cms.Engine.WebControls.Categories; 
using Telerik.Cms.Web.UI; 
using System.ComponentModel; 
using System.Collections; 
using Telerik.Cms.Engine; 
using Telerik.Blogs; 
using Telerik.Cms; 
 
/// <summary> 
/// Summary description for CategoriesTreeFiltered 
/// </summary> 
public class CategoriesTreeFiltered :CategoriesTree 
    public CategoriesTreeFiltered() 
    { 
    } 
#region properties 
    public override string LayoutTemplatePath 
    { 
        get 
        { 
            return "~/Sitefinity/ControlTemplates/Generic_Content/CategoriesTree.ascx"
        } 
    } 
 
    [Category("FilterByCategories")] 
    [TypeConverter("Telerik.Blogs.WebControls.SelectedBlogsConverter, Telerik.Blogs")] 
    [WebEditor("Telerik.Blogs.WebControls.BlogsSelector, Telerik.Blogs")] 
    public Guid[] SelectedBlogs 
    { 
        get 
        { 
            return this.selectedBlogs; 
        } 
        set 
        { 
            this.selectedBlogs = value; 
        } 
    } 
    
#endregion 
    #region Methods 
 
    protected override void BindCategories() 
    { 
        IList categories; 
 
        blogManager = new BlogManager("Blogs"); 
        if (this.selectedBlogs.Length == 0) 
            // call the base class we will not change anything. 
            base.BindCategories(); 
        else 
        { 
            IList allCategories = new List<ICategory>(); 
            if (string.IsNullOrEmpty(RootCategory)) 
            { 
                allCategories = blogManager.Content.GetCategories(0, 0, "CategoryName ASC"); 
            } 
            else 
            { 
                ICategory rootCategory = blogManager.Content.GetCategory(RootCategory); 
                allCategories = blogManager.Content.GetCategoriesTree(rootCategory); 
            } 
            IList allselectedBlogs = blogManager.GetBlogs(selectedBlogs); 
            IList<ICategory> filteredList = new List<ICategory>(); 
            foreach (IBlog blog in allselectedBlogs) 
            { 
                if (blog.PostsCount > 0) 
                { 
                    IList blogposts = blog.Posts; 
                    foreach (IContent cnt in blogposts) 
                    { 
                        string postCategory = (string)cnt.GetMetaData("Category"); 
                        if (!string.IsNullOrEmpty(postCategory)) 
                        { 
                            ICategory cat = Manager.GetCategory(postCategory); 
                            if (!filteredList.Contains(cat) && allCategories.Contains(cat)) 
                            { 
                                filteredList.Add(cat); 
                            } 
                            var parentId = cat.ParentCategoryID; 
                            while (parentId != Guid.Empty) 
                            { 
                                ICategory cat1 = Manager.GetCategory(parentId); 
                                if (!filteredList.Contains(cat1)) 
                                    filteredList.Add(cat1); 
                                parentId = cat1.ParentCategoryID; 
                            } 
                        } 
                    } 
                } 
            } 
             
          
        this.CategoriesTreeView.DataTextField = "CategoryName"
        this.CategoriesTreeView.DataFieldID = "ID"
        this.CategoriesTreeView.DataValueField = "ID"
        this.CategoriesTreeView.DataFieldParentID = "ParentCategoryID"
        this.CategoriesTreeView.DataSource = filteredList; 
        this.CategoriesTreeView.NodeDataBound +=new Telerik.Web.UI.RadTreeViewEventHandler(CategoriesTreeView_NodeDataBound); 
        this.CategoriesTreeView.DataBind(); 
 
        } 
 
    } 
    // you can unsubscribe from the event if you do not want to use ToolTip 
    void CategoriesTreeView_NodeDataBound(object sender, Telerik.Web.UI.RadTreeNodeEventArgs e) 
    { 
        ICategory nodeCategory = (ICategory)e.Node.DataItem; 
        e.Node.NavigateUrl = base.GetNodeUrl(nodeCategory.CategoryName, nodeCategory.ID.ToString()); 
        e.Node.ToolTip = nodeCategory.CategoryName; 
        
    } 
    #endregion 
    #region Private contstraints 
    private Guid[] selectedBlogs = new Guid[] {}; 
    private BlogManager blogManager; 
    #endregion 
 
  

 

 


3 comments

Leave a comment
  1. sathi Dec 17, 2010
    Great Blog I am Certified to your blog Because I have Searched and visited blog contents are Unique. if your blog were not post unique so I would not post my comment.
    Dog Boots



  2. multiple choice questions Nov 27, 2012
    Nothing is more absolutely frustrating to
    any person than needing to write one's thoughts clearly and concisely on paper,
    in the form of a personal letter to a friend or loved one, a statement of
    purpose required in a university application, a professional summation of job
    performance required by a manager, or an essay, research paper, or thesis
    required by a high school instructor or college professor for a course grade,
    and not having the fundamental skills to do so.
  3. Phoebe Wilsons Mar 25, 2013
    But what is the use of this line return "~/Sitefinity/ControlTemplates/Generic_Content/CategoriesTree.ascx";  ?

    Leave a comment