Feather: Extend the Navigation widget model
You can extend the model of the Feather Navigation widget and thus modify the widget's display settings. You first implement a custom model that represents page nodes with descriptions and then modify the widget's view to use the new model.
PREREQUISITES: To bind a new implementation for the navigation model, you need Ninject installed on your web application project. If you do not have a reference to Ninject, install it using the Package Manager console by typing Install-Package Ninject
Implement the custom model
First, in the Mvc/Models/Navigation folder you create a new view model that represents a page node. The model inherits from the default model, so it is usable. Add an extra Description
property to the model:
public class CustomNodeViewModel : NodeViewModel
{
public CustomNodeViewModel() : base()
{
this.description = this.GetDescription();
}
public CustomNodeViewModel(SiteMapNode node, string url, string target, bool isCurrentlyOpened, bool hasChildOpen)
: base(node, url, target, isCurrentlyOpened, hasChildOpen)
{
this.description = this.GetDescription();
}
public string Description
{
get
{
return this.description;
}
}
private string GetDescription()
{
var pageNode = this.OriginalSiteMapNode as PageSiteNode;
if (pageNode != null)
{
return pageNode.Description ?? string.Empty;
}
else
{
return string.Empty;
}
}
private readonly string description;
}
As a result, the new model extracts page descriptions.
Next, you create a new model that is aware of the custom view model. The new navigation model inherits from the default model and exposes the same constructors:
public class CustomNavigationModel : NavigationModel
{
public CustomNavigationModel()
: base()
{
}
public CustomNavigationModel(PageSelectionMode selectionMode, Guid selectedPageId, SelectedPageModel[] selectedPages, int? levelsToInclude, bool showParentPage, string cssClass, bool openExternalPageInNewTab)
: base(selectionMode, selectedPageId, selectedPages, levelsToInclude, showParentPage, cssClass, openExternalPageInNewTab)
{
}
// Other overrides here...
}
You then override the InstantiateNodeViewModel
method and its overloads in the new model:
protected override NodeViewModel InstantiateNodeViewModel(SiteMapNode node)
{
bool isSelectedPage = this.CurrentSiteMapNode != null && this.CurrentSiteMapNode.Key == node.Key;
string url = this.ResolveUrl(node);
string target = this.GetLinkTarget(node);
var hasSelectedChild = this.CurrentSiteMapNode != null && this.CurrentSiteMapNode.IsDescendantOf(node);
return new CustomNodeViewModel(node, url, target, isSelectedPage, hasSelectedChild);
}
protected override NodeViewModel InstantiateNodeViewModel(string url, string target)
{
return new CustomNodeViewModel(null, url, target, false, false);
}
Modify the view to use the new view model
You use the NavigationView.Tabs
view as a starting point. Wherever page nodes are enumerated, make sure to specify the new view model class and print the node's Description
:
@foreach(CustomNodeViewModel node in nodes)
{
<
li
class
=
"@GetClass(node)"
>
<
a
href
=
"@node.Url"
target
=
"@node.LinkTarget"
>@node.Title</
a
><
span
>@node.Description</
span
>
</
li
>
}
Rebind the model to the new implementation
You finally replace the original implementation of the Navigation widget model with the new model. You do this using Bootstrapper.Initialized
event. Place the following code in your Global.asax
file:
protected void Application_Start(object sender, EventArgs e)
{
Bootstrapper.Initialized += this.Bootstrapper_Initialized;
}
private void Bootstrapper_Initialized(object sender, Telerik.Sitefinity.Data.ExecutedEventArgs e)
{
if (e.CommandName == "Bootstrapped")
{
FrontendModule.Current.DependencyResolver.Rebind<
INavigationModel
>().To<
CustomNavigationModel
>();
}
}