For the code:
strMenuText.Append(RenderLink(mainlinkitem, x => x.NavigationItem.Url.StringToLink(), isEditable: true, contents: mainlinkitem.NavigationTitle));
Here mainlinkitem
is Navigation object for interface created for data template. I am using interfaces in this case and castle windsor creates dynamic proxy objects for this.
Things work ok until I try to use Page editor mode and below error shows up from glass mapper api.
Expression doesn't evaluate to a member x.NavigationItem.Url.StringToLink() at Glass.Mapper.Sc.GlassHtml.MakeEditable[T](Expression
1 field, Expression
1 standardOutput, T model, String parameters, Context context, Database database, TextWriter writer)
Note: StringToLink is extension method for converting external url in string
form to Glass mapper Glass.Mapper.Sc.Fields.Link
type.
public static Link StringToLink(this string urlvalue) { Link itemLink = new Link(); itemLink.Url = urlvalue; return itemLink; }
UPDATE
Code for menu user control:
public partial class MenuControl : GlassUserControl<INavigationFolder> { protected override void GetModel() { base.GetModel(); SiteLevelSettings siteSettings = SitecoreContext.GetItem<SiteLevelSettings>(Guid.Parse("Some GUID")); Model = siteSettings.HeaderMenuFolder; } protected void Page_Load() { if (!Page.IsPostBack) { LoadMenu(); } } private void LoadMenu() { StringBuilder strMenuText = new StringBuilder(); foreach (INavigationLink mainlinkitem in Model.ChildLinks) { if (CanRead(mainlinkitem)) { strMenuText.Append("<td class='menu-item'>"); if (mainlinkitem.ChildLinks != null && mainlinkitem.ChildLinks.Count() > 0) { strMenuText.Append("<ul>"); foreach (INavigationLink linkitem in mainlinkitem.ChildLinks) { if (CanRead(linkitem)) { strMenuText.Append("<li>"); if (linkitem.NavigationItem != null) { strMenuText.Append(RenderLink(linkitem, x => x.NavigationItem.Url.StringToLink(), isEditable: false, contents: linkitem.NavigationTitle)); } else if (linkitem.NavigationGeneralLink != null) { strMenuText.Append(RenderLink(linkitem, x => x.NavigationGeneralLink, isEditable: false, contents: linkitem.NavigationTitle)); } strMenuText.Append("</li>"); } } strMenuText.Append("</ul>"); } strMenuText.Append("<div class='nav-divider'>"); if (mainlinkitem.NavigationItem != null) { strMenuText.Append(RenderLink(mainlinkitem, x => x.NavigationItem.Url.StringToLink(), isEditable: false, contents: mainlinkitem.NavigationTitle)); } else if (mainlinkitem.NavigationGeneralLink != null) { strMenuText.Append(RenderLink(mainlinkitem, x => x.NavigationGeneralLink, isEditable: true, contents: mainlinkitem.NavigationTitle)); } strMenuText.Append("</div></td>"); } } ltrMenu.Text = strMenuText.ToString(); } private bool CanRead(IItem mainlinkitem) { var ItemId = mainlinkitem.TemplateId; var ItemIDObj = new Sitecore.Data.ID(ItemId); var contentdatabase = Sitecore.Context.Database; var item = contentdatabase.GetItem(ItemIDObj); return item.Access.CanRead(); } }
Navigation Folder interface for glass mapper:
[SitecoreType(TemplateId = "{Some GUID}")] public interface INavigationFolder : IItem { [SitecoreChildren(IsLazy = false)] IEnumerable<INavigationLink> ChildLinks { get; set; } }
Navigation Link interface for glass mapper:
[SitecoreType(TemplateId = "{Some GUID}")] public interface INavigationLink : IItem { [SitecoreField(FieldId = "{Some GUID}")] string NavigationTitle { get; set; } [SitecoreField(FieldId = "{Some GUID}")] IItem NavigationItem { get; set; } [SitecoreField(FieldId = "{Some GUID}")] Link NavigationGeneralLink { get; set; } [SitecoreField(FieldId = "{Some GUID}")] string ShortDescription { get; set; } [SitecoreChildren(IsLazy = false)] IEnumerable<INavigationLink> ChildLinks { get; set; } }
Note: This will code will generate menu similar to sitecore site
UPDATE
Url property in interface IItem
is defined as follows:
[SitecoreType(TemplateId = "{Some GUID}")] public interface IItem { [SitecoreId()] Guid ID { get; } [SitecoreInfo(Type = SitecoreInfoType.Language)] Language Language { get; } [SitecoreInfo(Type = SitecoreInfoType.Version)] int Version { get; } [SitecoreInfo(Type = SitecoreInfoType.Url)] string Url { get; } [SitecoreInfo(Type = SitecoreInfoType.TemplateId)] Guid TemplateId { get; } [SitecoreInfo(Type = SitecoreInfoType.Key)] string Key { get; } }