I came across a Sitemap generation code), the idea interested me enough to do a bit more research into the topic, and try to work out the details.
So here's some notes on the hows and whys of using code to change layout details. (I'm working on Sitecore 6.6 here, but this information is relevant to many versions of Sitecore)
You can view the layout details by enabling both the "Standard Fields" and "Raw Values" view of an item in Content Editor, and then looking at the Renderings field in the Layout region:
var page = Sitecore.Context.Database.GetItem("/sitecore/content/Home"); var field = page.Fields[Sitecore.FieldIDs.LayoutField]; string xml = LayoutField.GetFieldValue(field);
First we load a page, and then extract the Renderings field from it. The constant
Sitecore.FieldIDs.LayoutField
represents the name of the correct field. Finally the
LayoutField
class provides the
GetFieldValue()
method, which knows how to extract the data correctly.
If you look inside the code for this,
GetFieldValue()
uses another class called
XmlDeltas
to deal with the process of managing the deltas.
Once you have the XML, you have two choices about how to work with it. You could just manipulate the XML manually if you wanted. However the more supportable approach (which I'm interested here) is to use the API objects that Sitecore provides. And the class
LayoutDefinitions
manages this for us, and provides a method to parse the XML into objects:
var details = Sitecore.Layouts.LayoutDefinition.Parse(xml);
So in the same way this bit of UI shows, you start traversing these objects by finding the appropriate
Device
. You can either iterate them:
foreach(DeviceDefinition device in details.Devices) { // do something with device }
or you can find a specific one by ID (The ID is the GUID of the Device item under
/sitecore/layout/Devices
):
var device = details.GetDevice("{FE5D7FDF-89C0-4D99-9AA3-B5FBD009C9F3}");
Each of these devices then includes a series of Rendering Definitions - the things which need to be displayed when this device is being used. Again you can either iterate these, or extract specific ones. To iterate through the things that will be rendered, you can:
foreach(RenderingDefinition rendering in device.Renderings) { // do something with a rendering }
Each of these renderings have properties for things like the Datasource, the cache settings etc. They also have a unique ID for each individual rendering, as well as the ID of the Rendering / Sublayout that is being used for presentation. You can fetch specific renderings with:
RenderingDefinition r = device.GetRenderingByUniqueId("{43222D12-08C9-453B-AE96-D406EBB95126}");
(I don't believe these IDs are presented in the UI anywhere – so they make most sense in combination with iterating the collection)
Alternatively you can fetch by the UI component's ID. If you want to find exactly one rendering definition based on a specific control ID you can call:
RenderingDefinition r = device.GetRendering("{FE5D7FDF-89C0-4D99-9AA3-B5FBD009C9F3}");
or if you expect to get back more than one rendering definition based on a specific component you could call:
foreach(RenderingDefinition r = device.GetRenderings("{43222D12-08C9-453B-AE96-D406EBB95126}")) { // do something with a rendering }
In all of these cases, you can then update the
RenderingDefinition
object's properties in the usual way. For example, if you wanted to set a data source:
RenderingDefinition r = device.GetRenderingByUniqueId("{43222D12-08C9-453B-AE96-D406EBB95126}"); r.Datasource = "/somewhere/thing/stuff";
You can also create new Rendering Definitions and add them to the Device object, or remove Rendering Definitions from the device using the
device.AddRendering()
and
device.Renderings.Remove()
methods.
string newXml = details.ToXml(); var field = page.Fields[Sitecore.FieldIDs.LayoutField]; using (new Sitecore.Data.Items.EditContext(page)) { LayoutField.SetFieldValue(field, newXml); }
The Layout Details object knows how to serialise itself to XML via the
ToXml()
method, but we need to use the
LayoutField.SetFieldValue()
method to store this data to ensure that we save a delta rather than the whole layout definition.
[NB: After I wrote this, I realised that John West had already posted some of this detail on his blog. So if you're interested in his take on this, you may wish to read that post as well]
↑ Back to top