Checking if Content Part Field exists

Topics: Customizing Orchard, Writing themes
Sep 1, 2012 at 2:16 PM
Edited Sep 1, 2012 at 2:17 PM

Hi all

I'm migrating my modifications of Advanced Menu into native menu of Orchard 1.5.1.

I want to add custom css classes (or other attributes) to menu item. I'm doing it by just adding fields to Menu Part. Then I'm overriding MenuItem.cshtml in my theme, just like in the discussion: http://orchard.codeplex.com/discussions/390370. But there is one issue I can't bear with.

What if fields has not been created? There of course I got exception:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'Orchard.Core.Navigation.Models.MenuPart' does not contain a definition for 'CssClass'

 The thing is, I don't want to get exception. I have been trying:

if (Model.Content.ContentItem.MenuPart.CssClass != null)
{
    tag.AddCssClass(Model.Content.ContentItem.MenuPart.CssClass.Value);
}  

but it doesn't do the job. I read some ideas on Stackoverflow and tried using reflecion:

var CssClass = Model.Content.ContentItem.MenuPart.GetType().GetProperty("CssClass");
if (CssClass != null)
{
    tag.AddCssClass(CssClass.Value);
}

and good thing is, I don't get exception. Bad thing, that CssClass is always null. I don't know why. I assume that CssClass is not a simple property and there is some more complex structure behind.

Of course, I could use "try catch" but I think it is very nasty to use it and I'm trying different approach.

Could someone support me with correct solution?

Martin

Sep 5, 2012 at 1:17 PM

The solution has been posted by Sebastien a while ago (and will also make it into the core in a next version because questions about adding a custom CSS class has been asked several times).

The trick is to add a CssClass field to the MenuPart which allows you to write something like this in a MenuItem.cshtml template override:

@{
    // odd formatting in this file is to cause more attractive results in the output.
    var items = (IEnumerable)Enumerable.Cast(Model);

    dynamic contentItem = Model.Content.ContentItem;
}
@{
if (!HasText(Model.Text)) {
    @DisplayChildren(Model)
} else {
    string requestUrl = Request.Path.Replace(Request.ApplicationPath, string.Empty).TrimEnd('/').ToUpperInvariant();
    string modelUrl = Model.Href.Replace(Request.ApplicationPath, string.Empty).TrimEnd('/').ToUpperInvariant();
    if (requestUrl == modelUrl) { 
	    Model.Classes.Add("current");
    }
    if(items.Any()) {
        Model.Classes.Add("dropdown");
    }
    var tag = Tag(Model, "li");
    
    if (HasText(contentItem.MenuPart.CssClass.Value)) {
        tag.AddCssClass(contentItem.MenuPart.CssClass.Value);
    }
    
    @tag.StartElement
            
    @* morphing the shape to keep Model untouched*@
    Model.Metadata.Alternates.Clear(); 
    Model.Metadata.Type = "MenuItemLink";
    @Display(Model)
    
    if (items.Any()) {
        
    @DisplayChildren(Model)
} @tag.EndElement } }