问题
I'm looking for a working Dynamic Placeholder solution in MVC. There are at least two good descriptions of this "pattern" for use with WebForms:
- http://trueclarity.wordpress.com/2012/06/19/dynamic-placeholder-keys-in-sitecore/
- http://www.techphoria414.com/Blog/2011/August/Dynamic_Placeholder_Keys_Prototype
And I also found this blog explaining how to do it with MVC:
- http://blogs.perficient.com/portals/2012/10/17/sitecore-mvc-dynamic-placeholders/
First I have tried to implement Techphoria's method (with GUIDs) using techniques from the MVC blogpost (extension of the SitecoreHelper) and I also tried implementing the last described method (uses number suffixes that are incremented Column_1, Column_2, etc).
With all the variations I tried I didn't succeed in creating a working solution. My placeholders don't get properly named (I ended up with strange placeholder structures, or placeholders repeating themselves).
Without going into the specifics of my attempts, I would like to know if anyone else has a working solution ready that I could use.
If I can't find an already working solution, I will describe my problem in more detail and see if I can get that to work.
回答1:
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>
回答2:
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.
来源:https://stackoverflow.com/questions/15134720/sitecore-dynamic-placeholders-with-mvc