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

   —   
Example of integrating ComponentArt SiteMap. This article describes how to add a 3rd party sitemap control in Kentico CMS. In this example we will add a sitemap 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 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 SiteMap 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 SiteMap 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 SiteMapNode from node DataRow
 ///</summary>
 ///<param name="dr">DataRow with node data</param>
 ///<returns>New instance of SiteMapNode</returns>
 private ComponentArt.Web.UI.SiteMapNode CreateItem(DataRow dr)
 {
     ComponentArt.Web.UI.SiteMapNode Node = new ComponentArt.Web.UI.SiteMapNode();
 
     // Set menu caption
     if (this.EncodeMenuCaption)
     {
        Node.Text = HTMLHelper.HTMLEncode(GetMenuText(dr));
     }
     else
     {
        Node.Text = GetMenuText(dr);
     }       
    
     // Set link title
     if (this.RenderLinkTitle) Node.ToolTip = GetMenuText(dr);
 
     // Set URL
     Node.NavigateUrl = GetURL(dr);
    
     if (!Convert.ToBoolean(dr["DocumentShowInSiteMap"]))
     {
        // Disable item if it is set in properties
        Node.IncludeInSiteMap = false;
     }
    
     return Node;
 
 }

and

///<summary>
 /// Populates (recursively) the specified site map node with its subitems
 ///</summary>
 ///<param name="parentNodeId">NodeID of the node to be populated</param>
 ///<param name="parent">SiteMapNode to be populated with subitems</param>
 private void PopulateTreeItem(int parentNodeId, ComponentArt.Web.UI.SiteMapNode parent)
 {
 
     // Get child items from GroupedDataSource object
     ArrayList items = properties.GroupedDS.GetGroup(parentNodeId);
     if (items != null && parent.IncludeInSiteMap)
     {
 
        // 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 site map node, add it to menu and populate it with subitems
           ComponentArt.Web.UI.SiteMapNode child = CreateItem(dr);
           PopulateTreeItem(nodeId, child);
           parent.Nodes.Add(child);
 
         }
      }
 }

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

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

///<summary>
 /// Generates Site map tree structure and set its properties
 ///<param name="ds">DataSet with nodes data</param>
 ///<returns>New instance of SiteMap</returns>
 ///</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 site map node, add it to site map and populate it with subitems
              ComponentArt.Web.UI.SiteMapNode child = CreateItem(dr);          
              PopulateTreeItem(nodeId, child);
              this.SiteMap1.Nodes.Add(child);
           }
        }
     }
 }

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

///<summary>
 /// Generates Site map tree structure and set its properties
 ///<param name="ds">DataSet with nodes data</param>
 ///</summary>
 private void SetSiteMapProperties(DataSet ds)
 {
     // Generate tree structure
     GenerateTree(ds);
    
     // Set SiteMap properties
     this.SiteMap1.CssClass = this.MainCssClass;
     this.SiteMap1.ImagesBaseUrl = this.ImagesBaseUrl;
     this.SiteMap1.RootNodeCssClass = this.RootNodeCssClass;
     this.SiteMap1.RootNodeImageUrl = this.RootNodeImageUrl;
     this.SiteMap1.ParentNodeCssClass = this.ParentNodeCssClass;
     this.SiteMap1.ParentNodeImageUrl = this.ParentNodeImageUrl;
     this.SiteMap1.LeafNodeCssClass = this.LeafNodeCssClass;
     this.SiteMap1.LeafNodeImageUrl = this.LeafNodeImageUrl;
     this.SiteMap1.TreeShowLines = this.TreeShowLines;
     this.SiteMap1.TreeLineImagesFolderUrl = this.TreeLineImagesFolderUrl;
 
     GenerateTableLayout(this.ColsLayout, this.SiteMap1);
 }

This method is used in OnLoad event together with 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 SiteMap
     if (this.FilterControl != null)
     {
        this.FilterControl.InitDataProperties(this.properties);
     }
     // Set SiteMap properties
     SetSiteMapProperties(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.