16 August 2015

Loop through renderings in presentation and get the associated datasource

Today I was asked for how you can programmatically loop through all the renderings for an item and get the datasource information for each of the rendering. That sounded like an interesting question so I decided to post it here... What we wanted to do was to push the datasource items through workflow when the main item is beeing approved. We will split this in 2 posts so it is not too long here. So on this first post we will just see some code that will loop through the presentation and retrieve the list of item set in the renderings datasource. To make it a little different, lets try to find those where the rendering is inside a specific placeholder and a device

Well I first started to create a context class that will have method like the following:  
        /// 
        /// Return renderings for a specific Placeholder for the current item and a specific device
        /// 
        /// 
        /// 
        /// 
        public IEnumerable GetRenderings(string placeholderKey, string deviceName)
        {
            var currentItem = Sitecore.Context.Item;

            Sitecore.Data.Fields.LayoutField layoutField = new Sitecore.Data.Fields.LayoutField(currentItem);
            Sitecore.Layouts.RenderingReference[] renderings = layoutField.GetReferences(GetDeviceItem(deviceName));

            var filteredRenderingList = new List();

            foreach (var rendering in renderings)
            {
                if (rendering.Placeholder.Contains(placeholderKey))
                {
                    filteredRenderingList.Add(new RenderingItemWrapper(rendering.RenderingItem));
                }
            }

            return filteredRenderingList;
        }

        /// 
        /// Return the settings including datasource ID for the renderings in a specific placeholder 
        /// For current item and specific device
        /// 
        /// 
        /// 
        /// 
        public IEnumerable GetRenderingsSettings(string placeholderKey, string deviceName)
        {
            var currentItem = Sitecore.Context.Item;

            Sitecore.Data.Fields.LayoutField layoutField = new Sitecore.Data.Fields.LayoutField(currentItem);
            Sitecore.Layouts.RenderingReference[] renderings = layoutField.GetReferences(GetDeviceItem(deviceName));

            var filteredRenderingList = new List();

            foreach (var rendering in renderings)
            {
                if (rendering.Placeholder.Contains(placeholderKey))
                {
                    filteredRenderingList.Add(new RenderingSettingsWrapper(rendering.Settings));
                }
            }

            return filteredRenderingList;
        }

        /// 
        /// Get the Device from the context database and the Device name
        /// 
        /// 
        /// 
        private Sitecore.Data.Items.DeviceItem GetDeviceItem(string deviceName)
        {
            if (Sitecore.Data.ID.IsID(deviceName))
            {
                return Sitecore.Context.Database.Resources.Devices.GetAll().Where(d => d.ID.Guid == new Guid(deviceName)).First();
            }
            else
            {
                return Sitecore.Context.Database.Resources.Devices.GetAll().Where(d => d.Name.ToLower() == deviceName.ToLower()).First();
            }
        }



You will note the difference between the IRenderingItemWrapper and IRenderingSettingsWrapper
The later has all the information about the Datasource Item.

Then you can have a method that will loop through your IEnumerable then check your datasource information:

        /// 
        /// Get the Datasources for all renderings inside a placeholders
        /// 
        /// 
        /// 
        public IEnumerable GetRenderingDatasources(string placeholderKey)
        {
            var renderingDatasources = new List();

            IEnumerable renderingsSettings = _presentationContext.GetRenderingsSettings(placeholderKey);
            foreach (var renderingSettings in renderingsSettings)
            {
                if (renderingSettings.DataSource != null)
                {
                    Sitecore.Data.Items.Item datasourceItem;
                    if (Sitecore.Data.ID.IsID(renderingSettings.DataSource))
                    {
                        datasourceItem = _sitecoreContext.GetItem(new Guid(renderingSettings.DataSource));
                    }
                    else
                    {
                        datasourceItem = _sitecoreContext.GetItem(renderingSettings.DataSource);
                    }

                    if (datasourceItem == null)
                        continue;

                    renderingDatasources.Add(datasourceItem);
                }
            }

            return renderingDatasources;
        }


Hope that help anyone...

1 comment:

  1. Thanks for sharing!
    Although my eyes hurt seeing such long rules, especially:
    "GetAll().Where(predicate).First()"
    More readable AND efficiƫnt code would be a simple:
    ".First(predicate)"

    ReplyDelete