Custom Menu using Repeater
I have a custom control in which I am trying to render a menu using a repeater and a nested repeater. When I run it something is happening as a result of the nested repeater and it's databinding. I'm fairly sure the template is right as it was taken from an MSDN article.
Error
InvalidOperationException: Cannot convert from string.]
Telerik.Sitefinity.Web.UI.Templates.Attribute..ctor(String name, String value, ObjectBuilder builder, PropertyDescriptorCollection properties) +1350
Telerik.Sitefinity.Web.UI.Templates.TemplateParser.CreateObjectBuilder(HtmlChunk chunk) +414
Telerik.Sitefinity.Web.UI.Templates.TemplateParser.ParseChunk(HtmlChunk chunk) +75
Telerik.Sitefinity.Web.UI.Templates.TemplateParser.Parse() +187
The Control
public partial class CustomNavigationControl : SimpleView protected override string LayoutTemplateName get return CustomNavigationControl.layoutTemplateName; protected override void InitializeControls(Telerik.Sitefinity.Web.UI.GenericContainer container) // base.InitializeControls(container); private const string layoutTemplateName = "JHFControls.Resources.Views.CustomNavigationControl.ascx"; <%@ Control Language="C#" %> <asp:Repeater runat="server" ID="menu" DataSourceID="SiteMapDataSource1"> <HeaderTemplate> <ul id="topnav"> </HeaderTemplate> <ItemTemplate> <li> <asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl='<%# Eval("Url") %>'><%# Eval("Title") %></asp:HyperLink> <asp:Repeater ID="submenu" runat="server" DataSource='<%# ((SiteMapNode) Container.DataItem).ChildNodes %>'> <HeaderTemplate> <ul> </HeaderTemplate> <ItemTemplate> <li> <asp:HyperLink ID="HyperLink2" runat="server" NavigateUrl='<%# Eval("Url") %>'><%# Eval("Title") %></asp:HyperLink> </li> </ItemTemplate> <FooterTemplate> </ul> </FooterTemplate> </asp:Repeater> </li> </ItemTemplate> <FooterTemplate> </ul> </FooterTemplate> </asp:Repeater> <asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" ShowStartingNode="false" ViewStateMode="Disabled" /> Hello Dallas,
Remove the comment from base.InitializeControls(container)
protected override void InitializeControls(Telerik.Sitefinity.Web.UI.GenericContainer container) // base.InitializeControls(container); Error 1 Cannot call an abstract base member:
'Telerik.Sitefinity.Web.UI.SimpleView.InitializeControls(Telerik.Sitefinity.Web.UI.GenericContainer)'
Hi Dallas,
OK, yes you should not call the base when you inherit from SimpleView. Have you set CustomNavigationControl.ascx Build Action as "Embed Resource"? Can you remove the code inside <ItemTemplate> from both the Repeaters to see whether the error will appear.
Regards,
Ivan Dimitrov
the Telerik team
The control is an embedded resource. The error occurs on the second binding.
<asp:Repeater ID="submenu" runat="server" DataSource='<%# ((SiteMapNode) Container.DataItem).ChildNodes %>'> Hello Dallas Beek,
Sitefinity uses its own parser for parsing embedded resources. Compared to the ASP.NET parser, this parser has limited capabilities for parsing C# code. In the case with your template code, the non-parsable expression is,
<%# ((SiteMapNode) Container.DataItem).ChildNodes %><%@ Control Language="C#" %><asp:Repeater runat="server" ID="menu" DataSourceID="SiteMapDataSource1"> <HeaderTemplate> <ul id="topnav"> </HeaderTemplate> <ItemTemplate> <li> <asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl='<%# Eval("Url") %>'><%# Eval("Title") %></asp:HyperLink> <asp:Repeater ID="submenu" runat="server"> <HeaderTemplate> <ul> </HeaderTemplate> <ItemTemplate> <li> <asp:HyperLink ID="HyperLink2" runat="server" NavigateUrl='<%# Eval("Url") %>'><%# Eval("Title") %></asp:HyperLink> </li> </ItemTemplate> <FooterTemplate> </ul> </FooterTemplate> </asp:Repeater> </li> </ItemTemplate> <FooterTemplate> </ul> </FooterTemplate></asp:Repeater><asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" ShowStartingNode="false" ViewStateMode="Disabled" />public partial class CustomNavigationControl : SimpleView protected override string LayoutTemplateName get return CustomNavigationControl.layoutTemplateName; protected override void InitializeControls(Telerik.Sitefinity.Web.UI.GenericContainer container) container.GetControl<Repeater>("menu", true).ItemDataBound += new RepeaterItemEventHandler(CustomNavigationControl_ItemDataBound); // base.InitializeControls(container); void CustomNavigationControl_DataBinding(object sender, EventArgs e) void CustomNavigationControl_ItemDataBound(object sender, RepeaterItemEventArgs e) if (e.Item.ItemType.ToString() == "Item") var secondRepeater = e.Item.FindControl("submenu") as Repeater; secondRepeater.DataSource = ((SiteMapNode)e.Item.DataItem).ChildNodes; secondRepeater.DataBind(); private const string layoutTemplateName = "Telerik.Sitefinity.Resources.Templates.PublicControls.CustomNavigationControl.ascx";Thank you for replying, your answer to the parsing is what I assumed. I worked through it by creating a new sitemapdatasource as below.
<%@ Control Language="C#" %> <asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" ShowStartingNode="false" ViewStateMode="Disabled" /> <asp:Repeater runat="server" ID="menu" DataSourceID="SiteMapDataSource1"> <HeaderTemplate> <div class="pageListWrap"> <h1> <asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl='<%# Eval("Url") %>'><%# Eval("Title") %></asp:HyperLink> </h1> </HeaderTemplate> <ItemTemplate> <asp:SiteMapDataSource ID="SiteMapDataSource2" runat="server" ShowStartingNode="False" StartingNodeUrl='<%# Eval("Url") %>' ViewStateMode="Disabled" /> <asp:Repeater runat="server" ID="menu" DataSourceID="SiteMapDataSource2"> <ItemTemplate> <li> <asp:HyperLink ID="HyperLink2" runat="server" NavigateUrl='<%# Eval("Url") %>'><%# Eval("Title") %></asp:HyperLink> </li> </ItemTemplate> </asp:Repeater> </ItemTemplate> <FooterTemplate> </div> </FooterTemplate> </asp:Repeater>