3

Following this article, I managed to achieve adding a rendering programmatically. But it will add the new rendering, always at the last position.

Is it possible to add it at a particular index/position?

Say, I have multiple items that have the layout structure like

header
rendering 1
rendering 2
footer

and I would like to add the new rendering just above the footer for every such item.

2 Answers 2

7

There is a method deviceDefinition.Insert(index, renderingDefinition) that should do the trick. The DeviceDefinition holds the RenderingDefinitions in an ArrayList, and this Insert method will insert the rendering definition at the specified index in that ArrayList.

The AddRendering method -as mentioned in the article you referred to in the question- will always add your renderingdefinition at the end of the ArrayList, causing your new rendering to appear at the last position.

Based on the code in the article you mentioned, this would result into:

Database masterDatabase = Database.GetDatabase("master");
Item sampleItem = masterDatabase.GetItem("...");
string renderingXml = sampleItem["__Renderings"];
LayoutDefinition layoutDefinition = new LayoutDefinition();
layoutDefinition.LoadXml(renderingXml);

string defaultDeviceId = "{FE5D7FDF-89C0-4D99-9AA3-B5FBD009C9F3}";
DeviceDefinition deviceDefinition = layoutDefinition.GetDevice(defaultDeviceId);
string sampleLayoutId = "{14030E9F-CE92-49C6-AD87-7D49B50E42EA}";
deviceDefinition.Layout = sampleLayoutId;

string sampleRenderingId = "{493B3A83-0FA7-4484-8FC9-4680991CF743}";
RenderingDefinition renderingDefinition = new RenderingDefinition();
renderingDefinition.ItemID = sampleRenderingId;
renderingDefinition.Placeholder = "content";

// begin adapted code
var index = ...
deviceDefinition.Insert(index, renderingDefinition);
// end adapted code

string outputXml = layoutDefinition.ToXml();
sampleItem.Editing.BeginEdit();
sampleItem["__Renderings"] = outputXml;
sampleItem.Editing.EndEdit();

Defining the index depends a bit on how your renderings and placeholders are set. If the new rendering is the first in a placeholder, you could just add it at the beginning. Worst case scenario is that you need to search in the ArrayList for the footer.

2

A slightly different technique that I took was to incorporate a "Switcher" rendering. This is a controller rendering with no view/model compliment. Via some settings, I dynamically pull the rendering and datasource I want to "switch" into the existing location.

Example

  • Layout
    • Header
    • Some Content
    • Switcher
    • Footer

SwitcherController.cs

var stringBuilder = new StringBuilder();

var rendering = new Rendering
{
    DataSource = datasourceItem.ID.ToString(),
    RenderingItemPath = renderingItem.ID.ToString()
};

var renderingArgs = new RenderRenderingArgs(rendering, new StringWriter(stringBuilder));

CorePipeline.Run("mvc.renderRendering", renderingArgs);

return Content(stringBuilder.ToString());

You need to obtain the proper RenderingItem and DatasourceItem by your own means. There are additional RenderingArgs properties that may be set if your need suffices. Note that there are additional verification steps omitted (verify rendering type, verify datasource type, etc.)

By running mvc.renderRendering, the switched renderings will run through the standard Sitecore rendering pipeline.

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.