Tuesday, March 25, 2008

The Controls collection cannot be modified because the control contains code blocks (i.e. <% %>)

This one hit me some time ago but was easy to work around. Today I had to face it in a ListView's LayoutTemplate:

<LayoutTemplate>
    <asp:PlaceHolder runat="server" ID="itemPlaceholder"></asp:PlaceHolder>
    <% if ( ApplicationUser.IsCurrentUserTheAdmin )
       { %>
    <hr />
    <asp:ImageButton ID="SwitchAddSectionButton" runat="server" OnClick="SwitchAddSectionButton_Click"
        ImageUrl="~/Resources/item_add.gif" />
    <% } %>
</LayoutTemplate>

As you can see there is a dynamic part of the template which is available to users with sufficient priviledges.


Although google provides a lot of articles referening the issue, the solution I've came up is amazingly simple:



<LayoutTemplate>
    <asp:PlaceHolder runat="server" ID="itemPlaceholder"></asp:PlaceHolder>
    <div runat="server">
        <% if ( ApplicationUser.IsCurrentUserTheAdmin )
           { %>
        <hr />
        <asp:ImageButton ID="SwitchAddSectionButton" runat="server" 
            OnClick="SwitchAddSectionButton_Click"
            ImageUrl="~/Resources/item_add.gif" />
        <% } %>
    </div>
</LayoutTemplate>
Note that the only difference is the <div ... runat="server"> tag which contains all other additional controls in a control tree.

3 comments:

Anonymous said...

You could also try extending the listview and implementing the following method:

protected override void CreateLayoutTemplate()
{
base.CreateLayoutTemplate();

if (this.Controls.Count == 1)
this.Controls[0].DataBind();
}

This allows you to use databinding syntax within the LayoutTemplate (which seems less of a hack).

Björn said...

Thank you! Works fine!

Nisha said...

Nice one :)