Integrating 3rd party components in Kentico CMS – Component Art TreeView

   —   
Example of integrating ComponentArt TreeView. This article describes how to add a 3rd party sitemap control in Kentico CMS. In this example we will add a TreeView control from ComponentArt.
At first, you will need to download and install Web.UI 2008.2 for ASP.Net (registration required). You can choose there from 4 different platform builds, we were working with ASP .NET 3.5 build in this example so we recommend to use same build to ensure compatibility. You can either use the trial mode or you can buy the components from ComponentArt.

After the installation you can find (typically) in c:\Program Files\ComponentArt\Web.UI 2008.2 for ASP.NET 3.5\ this DLL file ComponentArt.Web.UI.dll. Please copy this file to you web project’s BIN folder. Now you are ready to develop custom site map web part (control) using the ComponentArt. Please follow these steps:

Open the web project in Visual Studio and follow this description how to create new web part (please do not forget to change the inherited class to CMSAbstractWebPart).

In the Toolbox you can find added new controls from ComponentArt. Please drag the TreeView control and drop it to the ascx code of your control. Switch to the code behind.

We use same practice as in our previous article which was dealing with integrating Component Art menu control and we will some properties object, to ensure the control will be able to handle some properties:

// MenuProperties object - ensures the data integrity and provides GroupedDataSource
    CMSMenuProperties properties = new CMSMenuProperties();

Now you can add to your control some common and recommended properties like ClassNames (document types), CombineWithDefaultCulture, CultureCode, MaxRelativeLevel, OrderBy, Path, SelectOnlyPublished, SiteName, WhereCondition and FilterControl. For example:

///<summary>
    /// Gets or sets the nodes path
    ///</summary>
    public string Path
    {
        get
        {
            return DataHelper.GetNotEmpty(ValidationHelper.GetString(this.GetValue("Path"), this.properties.Path), this.properties.Path);
        }
        set
        {
            this.SetValue("Path", value);
            this.properties.Path = value;
        }
    }

You should use same practice to create custom properties connected with settings and design of TreeView control. To store these properties in database appropriate webpart properties in properties tab of your custom webpart in SiteManager->Development->Webparts should be created.


The main logic of the control is performed in SetupControl() method. If you have defined the properties, you need to initialize them in this method:

///<summary>
 /// Initializes the control properties
 ///</summary>
 protected void SetupControl()
 {
 
     if (this.StopProcessing)
     {
        this.properties.StopProcessing = true;
     }
 
     else
     {
         // Initialize the CMSMenuProperties object
         properties.ParentControl = this;
         properties.Path = this.Path;
         properties.WhereCondition = this.WhereCondition;
         properties.SiteName = this.SiteName;
         properties.SelectOnlyPublished = this.SelectOnlyPublished;
         properties.OrderBy = this.OrderBy;
         properties.CultureCode = this.CultureCode;
         properties.CombineWithDefaultCulture = this.CombineWithDefaultCulture;
         properties.ClassNames = this.ClassNames;
         properties.MaxRelativeLevel = this.MaxRelativeLevel;
         properties.CacheMinutes = this.CacheMinutes;
         properties.CacheItemName = this.CacheItemName;
         properties.CheckPermissions = this.CheckPermissions;
         properties.CacheDependencies = this.CacheDependencies;
 
         properties.DataSource = properties.GetDataSource();
        
     }
 }

Now, you will need to create new methods which will help with creating and populating the items. For example:

///<summary>
 /// Creates new Instance of TreeView Node from node DataRow
 ///</summary>
 ///<param name="dr">DataRow with node data</param>
 ///<returns>New instance of TreeViewNode</returns>
 private ComponentArt.Web.UI.TreeViewNode CreateItem(DataRow dr)
 {
     string imageUrl;
     ComponentArt.Web.UI.TreeViewNode Node = new ComponentArt.Web.UI.TreeViewNode();
 
     // Set menu caption
     Node.Text = GetMenuText(dr);
 
     // Choose node image URL
     if (this.DisplayDocumentTypeImages)
     {
        imageUrl = GetDocumentTypeImage(dr);
        if (imageUrl.Length != 0)
        {
           Node.ImageUrl = imageUrl;
           Node.SelectedExpandedImageUrl = imageUrl;
          Node.ExpandedImageUrl = imageUrl;
        }
     }
 
     // Set nodes URL
     if (this.SetNodeURL)
     { Node.NavigateUrl = GetURL(dr); }
 
     // Hiding documents according to setting in properties
     if (this.HideInNavigation)
     {
        if (Convert.ToBoolean(dr["DocumentMenuItemHideInNavigation"]))
        {
           Node.Visible = false;
        }
     }
     return Node;
 }

and

///<summary>
 /// Populates (recursively) the specified Tree view node with its subitems
 ///</summary>
 ///<param name="parentNodeId">NodeID of the node to be populated</param>
 ///<param name="parent">TreeViewNode to be populated with subitems</param>
 private void PopulateTreeItem(int parentNodeId, ComponentArt.Web.UI.TreeViewNode parent)
 {
     // Get child items from GroupedDataSource object
     ArrayList items = properties.GroupedDS.GetGroup(parentNodeId);
     if (items != null )
     {
        // Append all childs
        foreach (DataRow dr in items)
        {
           // Get menu item nodeid (to get the child items)
           int nodeId = ValidationHelper.GetInteger(dr["NodeID"], 0);
 
           // Create tree view node, add it to tree and populate it with subitems
           ComponentArt.Web.UI.TreeViewNode child = CreateItem(dr);
           parent.Nodes.Add(child);
                              
           if (!this.CurrentTreeViewNodeFound && ValidationHelper.GetString(dr["NodeGUID"], "") == CMS.CMSHelper.CMSContext.CurrentDocument.NodeGUID.ToString())
           {   // expand current path
               if (this.ExpandCurrentPath)
               {
                  this.ExpandParentNodes(child.ParentNode);
               }
               // expand sub tree
               if (this.ExpandSubTree)
               { 
                  child.Expanded = true;
               }
               this.CurrentTreeViewNodeFound = true;
            }
            // Populate resursively tree
            PopulateTreeItem(nodeId, child);
        }
     }
 }

As you can see, second method is recursively calling itself and also the CreateItem method. This ensures that all items are properly populated.

Next step is to create a method which will use mentioned two methods to build whole TreeView tree structure:

///<summary>
 /// Generates Tree view node tree structure from dataset
 ///<param name="ds">DataSet with nodes data</param>
 ///</summary>
 private void GenerateTree(DataSet ds)
 {
     // Get top node level
     if (ds.Tables[0].Rows.Count != 0)
     {
        int topNodeLevel = ValidationHelper.GetInteger(ds.Tables[0].Rows[0]["NodeLevel"], 0);
 
        // Get all the items in the top level
        foreach (DataRow dr in ds.Tables[0].Rows)
        {
           if (ValidationHelper.GetInteger(dr["NodeLevel"], 0) == topNodeLevel)
           {
              // Get node nodeid (to get the child items)
              int nodeId = ValidationHelper.GetInteger(dr["NodeID"], 0);
 
              // Create tree view node, add it to tree view and populate it with subitems
              ComponentArt.Web.UI.TreeViewNode child = CreateItem(dr);
              this.TreeView1.Nodes.Add(child);
 
              // Expand if node is in current path
              if (!this.CurrentTreeViewNodeFound && ValidationHelper.GetString(dr["NodeGUID"], "") == CMS.CMSHelper.CMSContext.CurrentDocument.NodeGUID.ToString())
              {  
                 //expand sub tree
                 if (this.ExpandSubTree)
                 {
                    child.Expanded = true;
                    this.CurrentTreeViewNodeFound = true;
                 }
                 this.TreeView1.SelectedNode=child;
              }
 
              // Populate resursively tree
              PopulateTreeItem(nodeId, child);
                   
           }
        }
     }
 }

Finally method SetTreeViewProperties is created to set properties of Component Art TreeView control and to assign created tree structure to this control.

///<summary>
 /// Generates Tree view tree structure and set its properties
 ///<param name="ds">DataSet with nodes data</param>
 ///</summary>
 private void SetTreeViewProperties(DataSet ds)
 {
     // Generate tree structure
     GenerateTree(ds);
 
     // Set TreeView properties
     this.TreeView1.CssClass = this.MainCssClass;
     this.TreeView1.NodeCssClass = this.NodeCssClass;
     this.TreeView1.NodeRowCssClass = this.NodeRowCssClass;
     this.TreeView1.SelectedNodeCssClass = this.SelectedNodeCssClass;
     this.TreeView1.HoverNodeCssClass = this.HoverNodeCssClass;
       
     // Set URL of node images
     if (!this.DisplayDocumentTypeImages)
     { this.TreeView1.ImagesBaseUrl = this.ImagesBaseUrl;
        this.TreeView1.ParentNodeImageUrl = this.ParentNodeImageUrl;
        this.TreeView1.ExpandedParentNodeImageUrl = this.ExpandedParentNodeImageUrl;
        this.TreeView1.LeafNodeImageUrl = this.LeafNodeImageUrl;
     }
     else
     {
        this.TreeView1.ParentNodeImageUrl = this.ImagesBaseUrl + '/' + this.ParentNodeImageUrl;
        this.TreeView1.ExpandedParentNodeImageUrl = this.ImagesBaseUrl + '/' + this.ExpandedParentNodeImageUrl;
        this.TreeView1.LeafNodeImageUrl = this.ImagesBaseUrl + '/' + this.LeafNodeImageUrl;
     }
   
     this.TreeView1.ParentNodeImageUrl = this.ParentNodeImageUrl;
     this.TreeView1.ExpandedParentNodeImageUrl = this.ExpandedParentNodeImageUrl;
     this.TreeView1.LeafNodeImageUrl = this.LeafNodeImageUrl;
     this.TreeView1.ShowLines = this.ShowLines;
     this.TreeView1.LineImagesFolderUrl = this.LineImagesFolderUrl;
     this.TreeView1.ExpandImageUrl = this.ExpandImageUrl;
     this.TreeView1.CollapseImageUrl = this.CollapseImageUrl;
     this.TreeView1.NoExpandImageUrl = this.NoExpandImageUrl;
     this.TreeView1.CollapseDuration = this.CollapseDuration;
     this.TreeView1.ExpandDuration = this.ExpandDuration;
     this.TreeView1.CollapseSlide = (SlideType)this.CollapseSlide;
     this.TreeView1.ExpandSlide = (SlideType)this.ExpandSlide;
       
     // Expand all nodes
     if (this.ExpandAllOnStartup)
     {
        this.TreeView1.ExpandAll();
     }
 }

This method is used in OnLoad event to ensure proper function of new feature included in version 4.0, data filtering:

///<summary>
 /// OnLoad
 ///</summary>
 protected override void OnLoad(EventArgs e)
 {
     base.OnLoad(e);
     //Set the filter to TreeView
     if (this.FilterControl != null)
     {
        this.FilterControl.InitDataProperties(this.properties);
     }
     // Set TreeView properties
     SetTreeViewProperties(properties.GetDataSource());
 }

You can download the complete code example from here. In the package are included sample CSS styles and web part properties and this KB article as well. Webpart is included in the zip package in the form of exported objects package, so you can import it to your CMS (package is prepared for 4.0 version) and then use it in your site and view the code in Visual Studio. The controls are imported to the ComponentArt folder under CMSWeparts.


See also:

Applies to: Kentico CMS 4.0, ComponentArt
Share this article on   LinkedIn

Juraj Ondrus

Hi, I am the Technical support leader at Kentico. I'm here to help you use Kentico and get as much as possible out of it.