Sitecore Swamp

Dive in the Sitecore Swamp

NAVIGATION - SEARCH

user control Literal content () is not allowed within?

To embed something into user control, but have an error like:

Here's the cure to it, and the thing embedded within the user control will neither show nor complaint an error.

    [ParseChildren(false)]
    [PersistChildren(true)]
    public partial class ProductTile : System.Web.UI.UserControl
    {

ParseChildrenAttribute 

The ParseChildrenAttribute class allows you to specify parsing logic for a custom server control by marking the server control with the ParseChildrenAttribute metadata attribute.

Marking your server control with the metadata attribute ParseChildren(true) instructs the parser to interpret the elements that are contained within the server control's tags as properties. In this scenario, the ChildrenAsProperties property is true.

Marking your server control with the metadata attribute ParseChildren(true,"<Default Property>") sets the DefaultProperty property to the name of the property that is passed into the attribute.

Marking your server control with the metadata attribute ParseChildren(false), the default value, instructs the parser to interpret the elements that are contained within the server control's tags as content that will be parsed with an associated ControlBuilder that is, as controls. In this scenario, the ChildrenAsProperties property is false.

PersistChildrenAttribute:
The PersistChildrenAttribute is used in combination with the ParseChildrenAttribute to determine how nested content of a control is interpreted. If PersistChildrenAttribute is true and ParseChildrenAttribute is false, the nested content contained within an ASP.NET server control is persisted as controls. If PersistChildrenAttribute is false and ParseChildrenAttribute is true, the nested content is persisted as properties of the server control. For more information about using attributes, see Extending Metadata Using Attributes.

Workaround of data binding for LayoutTempate

Data binding doesn't work inside the LayoutTempate of ListView. The workaround is to utilize the LayoutCreated event to do find-and-assign:

Markup:
<asp:ListView runat="server" OnLayoutCreated="SelectedFiedls_OnLayoutCreated">
    <LayoutTemplate>
        <asp:Literal runat="server" ID="SeletectedFieldsTotal" /> Criteria selected for comparison:</h5>
            <asp:PlaceHolder runat="server" ID="itemPlaceholder"></asp:PlaceHolder>
    </LayoutTemplate>
    <ItemTemplate>
        ...
    </ItemTemplate>
</asp:ListView>
Code-behind:
protected void SelectedFiedls_OnLayoutCreated(object senderEventArgs e)
{
     var selectedFieldsTotal = ((ListView)sender).FindControl("SeletectedFieldsTotal"as Literal;
     selectedFieldsTotal.Text = SelectedFields.Count().ToString();
}
------------------------------------------------------------------------------------------------------------------------------------------------------------
updated: 2014-01-17 11:49 AM

The method above has issues with ViewState, as the LayoutCreated event is raised when the layout template is created in the ListView control. Obvious, it's too early for ViesState.(see ASP.NET Page LifeCycle Overview)

If using my favorite ControlDataBind event handler:
protected void ControlDataBind(object senderEventArgs e)
{
    ((Control)sender).DataBind();
}
This work can be done like:
<asp:ListView runat="server" OnLayoutCreated="SelectedFiedls_OnLayoutCreated">
    <LayoutTemplate>
        <asp:PlaceHolder runat="server" OnLoad="ControlDataBind">
            <h5><%# SelectedFields.Count() %> Criteria selected for comparison:</h5>    
        </asp:PlaceHolder>
    </LayoutTemplate>
    <ItemTemplate>
        ...
    </ItemTemplate>
</asp:ListView>
Happy coding!!!