0

The following code will remove rendering from items. It works fine but the changes happen only in the Shared Layout.

Is there a way to read/update renderings in only a certain layout type - Shared or Final.

LayoutField layoutField = new LayoutField(targetItem.Fields[FieldIDs.LayoutField]);
LayoutDefinition layoutDefinition = LayoutDefinition.Parse(layoutField.Value);
DeviceDefinition deviceDefinition = layoutDefinition.GetDevice("{FE5D7FDF-89C0-4D99-9AA3-B5FBD009C9F3}");
DeviceDefinition ddef = layoutDefinition.GetDevice(deviceDefinition.ID.ToString());

/// Get the array of all renderings for the target page item                    
IEnumerable<RenderingDefinition> renderingsArray = ddef.Renderings.ToArray().Cast<RenderingDefinition>();  

ddef.Renderings = new ArrayList(renderingsArray.Where(r => r.ItemID != someRenderingId).ToList());

/// Save the layout changes                     
using (new SecurityDisabler())
{
       targetItem.Editing.BeginEdit();
       layoutField.Value = layoutDefinition.ToXml();
       targetItem.Editing.EndEdit();
}
2
  • 1
    you just need to update the first line in your code for the final layout - FieldIDs.FinalLayoutField . LayoutField layoutField = new LayoutField(targetItem.Fields[FieldIDs.FinalLayoutField]); – Mahendra Shekhawat Nov 3 '20 at 13:03
  • 2
    Have you considered using Sitecore PowerShell Extensions to do this work? There are commands for managing renderings. – Michael West Nov 3 '20 at 14:28
3

You can get the final and shared layout using the following code. You can refer Get amount of components on final layout programmatically

// Returns the number of shared and final renderings for an item.
// Final renderings are based on language/version of the item.
// This presumes there is only one device with renderings configured.
public static System.Tuple<int, int> CountRenderings(Sitecore.Data.Items.Item item)
{
    var sharedRenderingsCount = CountRenderings(item, Sitecore.FieldIDs.LayoutField);
    var finalRenderingCount = CountRenderings(item, Sitecore.FieldIDs.FinalLayoutField);
    return Tuple.Create(sharedRenderingsCount, finalRenderingCount);
}

private static int CountRenderings(Sitecore.Data.Items.Item item, Sitecore.Data.ID renderingFieldId)
{
    var field = item.Fields[renderingFieldId];
    var layoutXml = Sitecore.Data.Fields.LayoutField.GetFieldValue(field);
    var layout = Sitecore.Layouts.LayoutDefinition.Parse(layoutXml);
    var deviceLayout = layout.Devices[0] as Sitecore.Layouts.DeviceDefinition;
    return (deviceLayout?.Renderings.Count) ?? 0;
}

And to set it again you can follow this - http://rockpapersitecore.com/2016/07/merging-final-renderings-back-down-into-shared-renderings/. You can modify code as per your requirements -

//Grab the field that contains the layout
    var layoutField = new LayoutField(item.Fields[Sitecore.FieldIDs.LayoutField]);

    //Grab the field that contains the final layout
    var finalLayoutField = new LayoutField(item.Fields[Sitecore.FieldIDs.FinalLayoutField]);

    if (layoutField == null)
        throw new Exception("Couldn't find layout on: {0}".FormatWith(item.Name));

    if (finalLayoutField == null)
        throw new Exception("Couldn't find final layout on: {0}".FormatWith(item.Name));

    //If we don't have a final layout delta, we're good!
    if (string.IsNullOrWhiteSpace(finalLayoutField.Value))
    {
        return;
    }

    var finalLayoutDefinition = LayoutDefinition.Parse(finalLayoutField.Value);

    using (new EditContext(item))
    {
        layoutField.Value = finalLayoutDefinition.ToXml();
        item.Fields["__Final Renderings"].Reset();
        item.Editing.AcceptChanges();
    }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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