How to use sitecore query in datasource location?

2019-04-08 11:14发布

问题:

Is it possible to set the datasource location (not the datasource) to be a sitecore query?

What I'm trying to do is to have the sublayout set its datasource location to a folder under the item containing it (current item).

The sublayout datasource location should point to a folder under the current item. So I tried setting the datasource location to query:./Items/* but that did not work.

回答1:

You don't need the query -- the sublayout datasource location can simply use a relative path. e.g.

./Items

Obviously though, that folder needs to exist already. I've been meaning to blog this code, and it may be overkill but I'll post here since it may help you. The following can be added to the getRenderingDatasource pipeline to create a relative path datasource location if it doesn't exist already. Add it before the GetDatasourceLocation processor.

On the sublayout, you'll want to add a parameter contentFolderTemplate=[GUID] to specify the template of the item that gets created.

public class CreateContentFolder
{
    protected const string CONTENT_FOLDER_TEMPLATE_PARAM = "contentFolderTemplate";

    public void Process(GetRenderingDatasourceArgs args)
    {
        Assert.IsNotNull(args, "args");
        Sitecore.Data.Items.RenderingItem rendering = new Sitecore.Data.Items.RenderingItem(args.RenderingItem);
        UrlString urlString = new UrlString(rendering.Parameters);
        var contentFolder = urlString.Parameters[CONTENT_FOLDER_TEMPLATE_PARAM];
        if (string.IsNullOrEmpty(contentFolder))
        {
            return;
        }
        if (!ID.IsID(contentFolder))
        {
            Log.Warn(string.Format("{0} for Rendering {1} contains improperly formatted ID: {2}", CONTENT_FOLDER_TEMPLATE_PARAM, args.RenderingItem.Name, contentFolder), this);
            return;
        }

        string text = args.RenderingItem["Datasource Location"];
        if (!string.IsNullOrEmpty(text))
        {
            if (text.StartsWith("./") && !string.IsNullOrEmpty(args.ContextItemPath))
            {
                var itemPath = args.ContextItemPath + text.Remove(0, 1);
                var item = args.ContentDatabase.GetItem(itemPath);
                var contextItem = args.ContentDatabase.GetItem(args.ContextItemPath);
                if (item == null && contextItem != null)
                {
                    string itemName = text.Remove(0, 2);
                    //if we create an item in the current site context, the WebEditRibbonForm will see an ItemSaved event and think it needs to reload the page
                    using (new SiteContextSwitcher(SiteContextFactory.GetSiteContext("system")))
                    {
                        contextItem.Add(itemName, new TemplateID(ID.Parse(contentFolder)));
                    }
                }
            }
        }
    }
}