简体   繁体   English

临时更改Sitecore项的布局

[英]Temporarily change a Sitecore item's layout

Using this code I managed to change the renderings on the current item. 使用此代码,我设法更改了当前项目的渲染。 However this changed it permenantly in Sitecore (the changes were could be seen in the CMS) and not temporarily, as I expected. 但是,这在Sitecore中进行了永久更改(更改可以在CMS中看到),而不是临时更改,这与我预期的一样。

void ReplaceLayout(Item item)
{
    if (item == null)
        return;

    using (new SecurityDisabler())
    {
        // New item
        LayoutField newLayoutField = new LayoutField(item.Fields[Sitecore.FieldIDs.LayoutField]);
        LayoutDefinition newLayoutDefinition = LayoutDefinition.Parse(newLayoutField.Value);

        DeviceDefinition newDeviceDefinition = newLayoutDefinition.GetDevice(Sitecore.Context.Device.ID.ToString());

        // Current item
        LayoutField layoutField = new LayoutField(Sitecore.Context.Item.Fields[Sitecore.FieldIDs.LayoutField]);
        LayoutDefinition layoutDefinition = LayoutDefinition.Parse(layoutField.Value);

        DeviceDefinition deviceDefinition = layoutDefinition.GetDevice(Sitecore.Context.Device.ID.ToString());
        deviceDefinition.Layout = newDeviceDefinition.Layout;
        deviceDefinition.Renderings = newDeviceDefinition.Renderings;

        Sitecore.Context.Item.Editing.BeginEdit();
        layoutField.Value = layoutDefinition.ToXml();
        Sitecore.Context.Item.Editing.EndEdit();
    }
}

I don't want to make permenant changes to the item, I just want to replace the currently displayed items renderings on the fly if some conditions are met. 我不想对项目进行永久更改,我只想在满足某些条件的情况下即时替换当前显示的项目渲染。 Does anyone know how to alter an item's layout in this way? 有人知道如何以这种方式更改项目的布局吗?

You explained in your comments that you want to display certain sublayouts in the sidebar depending on certain form parts/steps. 您在评论中解释说,您希望根据某些表单部件/步骤在边栏中显示某些子布局。 You can do that by adding a PlaceHolder that will fit the sublayouts (eg in your sidebar) and use this code to dynamically render sublayouts to it. 您可以通过添加一个适合子布局的PlaceHolder来做到这一点(例如,在边栏中),并使用此代码向其动态渲染子布局。

First you need an item (i call it a snippet item) that has the sublayout configured on its presentation settings. 首先,您需要一个在演示文稿设置中配置了子布局的项目(我称其为代码段项目)。 Then you can use code to render that item inside the placeholder (phSideBarPlaceHolder). 然后,您可以使用代码在占位符(phSideBarPlaceHolder)中呈现该项目。

// Load snippet item
Item snippet = Sitecore.Context.Database.GetItem("{id-or-path-of-snippet-item}");

// Get the first rendering from item's presentation definition
RenderingReference rendering = snippet.Visualization.GetRenderings(Sitecore.Context.Device, false).FirstOrDefault();

// We assume that its a Sublayout, but you can also check for xslt and create an XslFile() object
Sublayout sublayout = new Sublayout();
sublayout.DataSource = snippet.Paths.FullPath; // creates a reference to the snippet item, so you can pull data from that later on
sublayout.Path = rendering.RenderingItem.InnerItem["Path"];
sublayout.Cacheable = rendering.RenderingItem.Caching.Cacheable;

// Copy cache settings
if (rendering.RenderingItem.Caching.Cacheable)
{
    sublayout.VaryByData = rendering.RenderingItem.Caching.VaryByData;
    sublayout.VaryByDevice = rendering.RenderingItem.Caching.VaryByDevice;
    sublayout.VaryByLogin = rendering.RenderingItem.Caching.VaryByLogin;
    sublayout.VaryByParm = rendering.RenderingItem.Caching.VaryByParm;
    sublayout.VaryByQueryString = rendering.RenderingItem.Caching.VaryByQueryString;
    sublayout.VaryByUser = rendering.RenderingItem.Caching.VaryByUser;
}

// Now render the sublayout to the placeholder
phSideBarPlaceHolder.Controls.Add(sublayout);

If you need more info about how to read data the DataSource property inside the sublayout code, Mark Ursino has written an article about that: http://firebreaksice.com/using-the-datasource-field-with-sitecore-sublayouts 如果您需要有关如何读取子布局代码中DataSource属性数据的更多信息,Mark Ursino撰写了一篇有关该文章: http ://firebreaksice.com/using-the-datasource-field-with-sitecore-sublayouts

Sitecore constructs the rendering controls and inserts them into the page very early in the ASP.NET Webforms lifecycle. Sitecore构造了呈现控件,并在ASP.NET Webforms生命周期的早期就将其插入到页面中。 It's not likely you can easily do this on the layout itself. 您不太可能在布局本身上轻松完成此操作。 However, if you can evaluate your conditions outside the page (eg by examining the item itself), you can probably do this in the insertRenderings pipeline. 但是,如果您可以在页面外评估条件(例如,通过检查项目本身),则可以在insertRenderings管道中执行此操作。

Use ILSpy or another decompiler to check out Sitecore.Pipelines.InsertRenderings and Sitecore.Pipelines.InsertRenderings.Processors . 使用ILSpy或其他反编译器签出Sitecore.Pipelines.InsertRenderingsSitecore.Pipelines.InsertRenderings.Processors As with other pipelines, the order of execution of these processors is defined in Web.config. 与其他管道一样,这些处理器的执行顺序在Web.config中定义。 You will want to add a new processor after AddRenderings which evaluates your conditions (likely examining args.ContextItem ) and then modifies args.Renderings as needed. 您将需要在AddRenderings之后添加一个新处理器,以评估您的条件(可能检查args.ContextItem ),然后根据需要修改args.Renderings

In your previous question you were just looking to remove sublayouts. 上一个问题中,您只是想删除子布局。 That should be fairly easy here. 这在这里应该很容易。 Adding different sublayouts is more difficult since you would need to construct a RenderingReference . 添加不同的子布局更加困难,因为您将需要构造RenderingReference This may require that you actually create the XML definition needed for its constructor. 这可能需要您实际创建其构造函数所需的XML定义。 Or, if you have another item that defines the desired new layout, consider just changing args.ContextItem earlier in the pipeline. 或者,如果您还有另一个项定义了所需的新布局,请考虑在管道的前面更改args.ContextItem

Rather than change sitecore presentation, can you not place the 'form' control and sidebar within one parent control container? 除了更改Sitecore演示文稿,您还不能将“表单”控件和侧边栏放在一个父控件容器中吗? You would then have an an easy id for a sidebar container with which to conditionally populate controls programatically from the form control. 然后,您将获得一个侧边栏容器的简单ID,使用该ID可以通过程序从窗体控件有条件地填充控件。

Alternatively, could you add all the possible controls to the sidebar and 'activate' (or perhaps just make visible) the required control(s), maybe via session state variables? 另外,您是否可以通过会话状态变量将所有可能的控件添加到侧边栏并“激活”(或只是使其可见)所需的控件? (I dont know if this falls foul of some lifecycle or timing limitiation) (我不知道这是否违反某些生命周期或时间限制)

或者,您可以简单地使用条件渲染规则,根据您可以想到的任何逻辑来显示所需的渲染/子布局。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM