1

Using Sitecore 10.3

I would like to try the Multiroot Treelist field.
The requirement is to have an option for the author to choose from multiple locations, in the treelist field.

Could anyone please help me how to make use of this - https://kamsar.net/index.php/2015/05/A-Multiple-Root-Treelist-Field/

I have deployed the code. Do I need to add any patch config?

Because when I try with different "queries" in the "Source" of that field, nothing happens or it throws an error.

I have tried these queries:

{6CB91F7C-E722-4B9D-BA10-A909DC3BB80D}|{21329DDA-B575-44EA-A6A8-B172B6E9C738}

Those are IDs of two folders under the content node. The field is blank and the select option is unavailable.

datasource={6CB91F7C-E722-4B9D-BA10-A909DC3BB80D}|{21329DDA-B575-44EA-A6A8-B172B6E9C738} Throws an error.

query:/sitecore/content//*[@templateid='my banners folder template id']
This query works perfect in the rendering datasource field.
Wanted the same in the Treelist field also, but no luck.

3 Answers 3

2

Below are the few steps which you need to do:

  1. Create a new file MultiRootTreeList.cs and add the below code.
 namespace Sitecore.Foundation.CustomFields.Fields
{
    public class MultiRootTreeList : TreeList
    {
        protected override void OnLoad(EventArgs args)
        {
            Assert.ArgumentNotNull(args, "args");
            base.OnLoad(args);

            if (!Sitecore.Context.ClientPage.IsEvent)
            {
                // find the existing TreeviewEx that the base OnLoad added, get a ref to its parent, and remove it from controls
                var existingTreeView = (TreeviewEx)WebUtil.FindControlOfType(this, typeof(TreeviewEx));
                var treeviewParent = existingTreeView.Parent;

                existingTreeView.Parent.Controls.Clear(); // remove stock treeviewex, we replace with multiroot

                // find the existing DataContext that the base OnLoad added, get a ref to its parent, and remove it from controls
                var dataContext = (DataContext)WebUtil.FindControlOfType(this, typeof(DataContext));
                var dataContextParent = dataContext.Parent;

                dataContextParent.Controls.Remove(dataContext); // remove stock datacontext, we parse our own

                // create our MultiRootTreeview to replace the TreeviewEx
                var impostor = new Sitecore.Web.UI.WebControls.MultiRootTreeview();
                impostor.ID = existingTreeView.ID;
                impostor.DblClick = existingTreeView.DblClick;
                impostor.Enabled = existingTreeView.Enabled;
                impostor.DisplayFieldName = existingTreeView.DisplayFieldName;

                // parse the data source and create appropriate data contexts out of it
                var dataContexts = ParseDataContexts(dataContext);

                impostor.DataContext = string.Join("|", dataContexts.Select(x => x.ID));
                foreach (var context in dataContexts) dataContextParent.Controls.Add(context);

                // inject our replaced control where the TreeviewEx originally was
                treeviewParent.Controls.Add(impostor);
            }
        }

        /// <summary>
        /// Parses multiple source roots into discrete data context controls (e.g. 'dataSource=/sitecore/content|/sitecore/media library')
        /// </summary>
        /// <param name="originalDataContext">The original data context the base control generated. We reuse some of its property values.</param>
        /// <returns></returns>
        protected virtual DataContext[] ParseDataContexts(DataContext originalDataContext)
        {
            return new ListString(DataSource).Select(x => CreateDataContext(originalDataContext, x)).ToArray();
        }

        /// <summary>
        /// Creates a DataContext control for a given Sitecore path data source
        /// </summary>
        protected virtual DataContext CreateDataContext(DataContext baseDataContext, string dataSource)
        {
            DataContext dataContext = new DataContext();
            dataContext.ID = GetUniqueID("D");
            dataContext.Filter = baseDataContext.Filter;
            dataContext.DataViewName = "Master";
            if (!string.IsNullOrEmpty(DatabaseName))
            {
                dataContext.Parameters = "databasename=" + DatabaseName;
            }
            dataContext.Root = dataSource;
            dataContext.Language = Language.Parse(ItemLanguage);

            return dataContext;
        }
    }
}
  1. Create a new config file and add below code:
<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <controlSources>
      <source mode="on" namespace="Sitecore.Foundation.CustomFields.Fields" assembly="Sitecore.Foundation.CustomFields" prefix="customfields" />
    </controlSources>
  </sitecore>
</configuration>
  1. Switch to Core Database and Navigate to this location /sitecore/system/Field types/List Types (or you can create your custom folder)
  2. Create a new item using this template /sitecore/templates/System/Templates/Template field type
  3. Add Assembly and Class.

Now you will able to see your custom field in the template where you can select your custom field and add Datasource.

1

It does not require any config changes, I think you missed the Custom Field configuration to use this newly created field.

Add the Assembly and class details which extend the functionality of sitecore out of the box tree list class.

enter image description here

Reference: Multiple Datasource Treelist Field

Hope it helps!

1

You can also go with an existing module created by @Mikael.

This module basically adds two new template field types:

  • Treelist with Multiple Roots
  • TreelistEx with Multiple Roots

All in all, they should work identical to Sitecore's built-in Treelist and TreelistEx field types, but these supports multiple datasources in the Source string of the field.

Here is the GitHub repo for this module.

https://github.com/mikaelnet/sitecore-multi-treelist

Hope this helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.