Sitecore 'dynamic placeholders' with MVC Sitecore 'dynamic placeholders' with MVC asp.net asp.net

Sitecore 'dynamic placeholders' with MVC


I created this extension that creates dynamic placholders

public static class SitecoreHelper{    public static HtmlString DynamicPlaceholder(this Sitecore.Mvc.Helpers.SitecoreHelper helper, string dynamicKey)    {        var currentRenderingId = RenderingContext.Current.Rendering.UniqueId;        return helper.Placeholder(string.Format("{0}_{1}", dynamicKey, currentRenderingId));    }}

It creates a placeholder with the guid in the name.I also created a step in the pipeline that extracts the guid, and checks for placeholder settings.

Code to get placeholder settings to the dynamic placeholder If you create a dynamic placeholder with @Html.Sitecore().DynamicPlaceholder("test") - the following code takes the setting from the placeholder settings named test

 /// <summary>/// Handles changing context to the references dynamic "master" renderings settings for inserting the allowed controls for the placeholder and making it editable/// </summary>public class GetDynamicKeyAllowedRenderings : GetAllowedRenderings{    //text that ends in a GUID    private const string DYNAMIC_KEY_REGEX = @"(.+)_[\d\w]{8}\-([\d\w]{4}\-){3}[\d\w]{12}";    public new void Process(GetPlaceholderRenderingsArgs args)    {        Assert.IsNotNull(args, "args");        string placeholderKey = args.PlaceholderKey;        Regex regex = new Regex(DYNAMIC_KEY_REGEX);        Match match = regex.Match(placeholderKey);        if (match.Success && match.Groups.Count > 0)        {            placeholderKey = match.Groups[1].Value;        }        else        {            return;        }        // Same as Sitecore.Pipelines.GetPlaceholderRenderings.GetAllowedRenderings but with fake placeholderKey        Item placeholderItem = null;        if (ID.IsNullOrEmpty(args.DeviceId))        {            placeholderItem = Client.Page.GetPlaceholderItem(placeholderKey, args.ContentDatabase,                                                             args.LayoutDefinition);        }        else        {            using (new DeviceSwitcher(args.DeviceId, args.ContentDatabase))            {                placeholderItem = Client.Page.GetPlaceholderItem(placeholderKey, args.ContentDatabase,                                                                 args.LayoutDefinition);            }        }        List<Item> collection = null;        if (placeholderItem != null)        {            bool flag;            args.HasPlaceholderSettings = true;            collection = this.GetRenderings(placeholderItem, out flag);            if (flag)            {                args.CustomData["allowedControlsSpecified"] = true;                args.Options.ShowTree = false;            }        }        if (collection != null)        {            if (args.PlaceholderRenderings == null)            {                args.PlaceholderRenderings = new List<Item>();            }            args.PlaceholderRenderings.AddRange(collection);        }    }}

The following code removes the guid from the chrome data in the pageeditor

/// <summary>/// Replaces the Displayname of the Placeholder rendering with the dynamic "parent"/// </summary>public class GetDynamicPlaceholderChromeData : GetChromeDataProcessor{    //text that ends in a GUID    private const string DYNAMIC_KEY_REGEX = @"(.+)_[\d\w]{8}\-([\d\w]{4}\-){3}[\d\w]{12}";    public override void Process(GetChromeDataArgs args)    {        Assert.ArgumentNotNull(args, "args");        Assert.IsNotNull(args.ChromeData, "Chrome Data");        if ("placeholder".Equals(args.ChromeType, StringComparison.OrdinalIgnoreCase))        {            string argument = args.CustomData["placeHolderKey"] as string;            string placeholderKey = argument;            Regex regex = new Regex(DYNAMIC_KEY_REGEX);            Match match = regex.Match(placeholderKey);            if (match.Success && match.Groups.Count > 0)            {                // Is a Dynamic Placeholder                placeholderKey = match.Groups[1].Value;            }            else            {                return;            }            // Handles replacing the displayname of the placeholder area to the master reference            Item item = null;            if (args.Item != null)            {                string layout = ChromeContext.GetLayout(args.Item);                item = Sitecore.Client.Page.GetPlaceholderItem(placeholderKey, args.Item.Database, layout);                if (item != null)                {                    args.ChromeData.DisplayName = item.DisplayName;                }                if ((item != null) && !string.IsNullOrEmpty(item.Appearance.ShortDescription))                {                    args.ChromeData.ExpandedDisplayName = item.Appearance.ShortDescription;                }            }        }    }}

Edit

The web.config include settings are included below:

<sitecore>  <pipelines>    <getPlaceholderRenderings>      <processor         type="YourNamespace.Pipelines.GetPlaceholderRenderings.GetDynamicKeyAllowedRenderings, YourAssembly"        patch:before="processor[@type='Sitecore.Pipelines.GetPlaceholderRenderings.GetAllowedRenderings, Sitecore.Kernel']"/>    </getPlaceholderRenderings>    <getChromeData>      <processor        type="YourNamespace.Pipelines.GetChromeData.GetDynamicPlaceholderChromeData, YourAssembly"        patch:after="processor[@type='Sitecore.Pipelines.GetChromeData.GetPlaceholderChromeData, Sitecore.Kernel']"/>    </getChromeData>  </pipelines></sitecore> 


I downloaded the Integrated Dynamic Placeholders package from the sitecore marketplace. When building your page it increments the placeholders with configurable suffix appended to the end of the placeholder key to make them unique, according to their order on the presentation layer. Worked out of the box for me.