Kentico Layout Webpart Without The Chaos
In Kentico, a Layout Webpart
(or Layout Widget
) is a component you can drop into a
WebPartZone
that itself defines new WebPartZone
s.
If you check out the documentation on building your own custom Layout Webpart, you’ll find its a nutty mess of string concatenation, tables, and magic javascript. If you have more simpler needs, as I did, you will be sorely disappointed: who would want to maintain that over time.
The gist of the example given in the documentation is to generate a layout on
the fly, presumably calling AddZone
at the right place. This will output the
markup needed to dynamically create a zone for other Webparts to be added.
Just ask your designer to go in there and tweak some styles. They can update C# strings no problem right?
If, like me, you find this approach to be completely unacceptable, you might
start wondering about a better way. And indeed, spelunking in the CMS base
classes can prove fruitful. There is an overload for AddZone
that takes a
parameter for a container. So you just need to drop some placeholders in your
view (.ascx
file) and use them in the code behind:
<div class="row">
<div class="col-3">
<asp:PlaceHolder runat="server" ID="Left"></asp:PlaceHolder>
</div>
<div class="col-3">
<asp:PlaceHolder runat="server" ID="Middle"></asp:PlaceHolder>
</div>
<div class="col-3">
<asp:PlaceHolder runat="server" ID="Right"></asp:PlaceHolder>
</div>
</div>
Then just override PrepareLayout
as follows:
protected override void PrepareLayout()
{
// Dynamically generate zone IDs and names
StartLayout(keepExistingControls: true);
AddZone(this.ID + "_left", this.ID + " Left", Left);
AddZone(this.ID + "_middle", this.ID + " Middle", Middle);
AddZone(this.ID + "_right", this.ID + " Right", Right);
EndLayout(addToControls: false);
}
All of this comes about because the ZoneID
of a WebpartZone needs to be
unique on a page, even if you use the same Layout Webpart twice on a page. The
PrepareLayout hook allows you to reliably generate unique IDs.
Still, Kentico support should bury the example they have in their docs into an “Advanced Custom Layouts” section. No one’s first introduction to building a user control should be a StringBuilder.