2010-06-19 91 views
0

我想在MVC.NET分層菜單由XML

來創建分層基於XML的菜單
<?xml version="1.0" encoding="utf-8" ?> 
<NavigationMenu id="1" Name="myMenu" Lang="EN"> 
    <NavigationMenuGroup Header="Home" Name="header1" Link="/home" /> 
    <NavigationMenuGroup Header="Manage" Name="header2" Link="/options" /> 
    <NavigationMenuGroup Header="About" Name="header3" Link="/About" > 
    <NavigationMenuItem Header="Test1" Name="header5" Link="/page1" /> 
    <NavigationMenuItem Header="Test2" Name="header6" Link="/page2" /> 
    </NavigationMenuGroup> 
</NavigationMenu> 

我泛爲母版渲染部分菜單(NavMenu.ascx)的帶動下,數據將通過自定義基本控制器提供給主頁面。

NavMenu.ascx將生成類似於以下的代碼(易於插入jQuery或模擬器)。

<ul id="menu"> 
    <li> 
     <h2><a href="/home">Home</a></h2> 
    </li> 

    <li> 
     <h2><a href="/options">Manage</a></h2> 
    </li> 

    <li> 
     <h2><a href="/about">About</a></h2> 

      <li> 
      <h2><a href="/page2">Test1</a></h2> 
      </li> 
      <li> 
      <h2><a href="/page1">Test2</a></h2> 
      </li> 
    </li> 
</ul> 

我也有設置一組類反序列化。

namespace MyMVC.Helpers 
    { 
     public class XmlSerializerHelper<T> 
     { 
      public Type _type; 

      public XmlSerializerHelper() 
      { 
       _type = typeof(T); 
      } 

      public void Save(string path, object obj) 
      { 
       using (TextWriter textWriter = new StreamWriter(path)) 
       { 
        XmlSerializer serializer = new XmlSerializer(_type); 
        serializer.Serialize(textWriter, obj); 
       } 
      } 

      public T Read(string path) 
      { 
       T result; 
       using (TextReader textReader = new StreamReader(path)) 
       { 
        XmlSerializer deserializer = new XmlSerializer(_type); 
        result = (T)deserializer.Deserialize(textReader); 
       } 
       return result; 
      } 
     } 
} 

我不確定什麼是最好的方式做到這一點,而不打破MVC校長?

+0

是在你的菜單中的每個項目實際上是一個頭? – 2010-06-19 16:07:09

回答

3

試圖解決這個問題,我自己並與下面就來了。我用我的一個主要導航這需要一定的活動類(基於Drupal的菜單渲染):

XML:

<?xml version="1.0" encoding="utf-8" ?> 
<items> 
    <item title="Some Title" name="Test" text="Testing 1" link="1"> 
    <items> 
     <item name="Test" text="Testing 1-1" link="2"> 
     <items> 
      <item name="Test" text="About" link="/home/about" /> 
      <item name="Test" text="Testing 1-1-2" link="4" /> 
      <item name="Test" text="Testing 1-1-3" link="5" /> 
     </items> 
     </item> 
     <item name="Test" text="Testing 1-2" link="6" /> 
     <item name="Test" text="Testing 1-3" link="7" /> 
    </items> 
    </item> 
    <item name="Testame" text="Testing 2" link="8" /> 
    <item name="Test" text="Testing 3" link="9" /> 
    <item name="Test" text="Testing 4" link="10" /> 
    <item name="Test" text="Testing 5" link="11" /> 
    <item title="Some Title" name="Test" text="Testing 6" link="1"> 
    <items> 
     <item name="Test" text="Testing 6-1" link="12"> 
     <items> 
      <item name="Test" text="Testing 6-1-1" link="13" /> 
      <item name="Test" text="Testing 6-1-2" link="14" /> 
      <item name="Test" text="Testing 6-1-3" link="15" /> 
     </items> 
     </item> 
     <item name="Test" text="Testing 6-2" link="16" /> 
     <item name="Test" text="Testing 6-3" link="17" /> 
    </items> 
    </item> 
    <item name="Test" text="Testing 7" link="18" /> 
    <item name="Test" text="Testing 8" link="19"> 
    <items> 
     <item name="Test" text="Testing 8-1" link="20" /> 
     <item name="Test" text="Testing 8-2" link="21" /> 
     <item name="Test" text="Testing 8-3" link="22" /> 
    </items> 
    </item> 
</items> 

助手:

public static class Helpers 
    { 

     public static MvcHtmlString Menu(this HtmlHelper helper, string name, string e = null, object attributes = null) 
     { 
      string filepath = helper.ViewContext.HttpContext.Server.MapPath(name + ".xml"); 

      XPathDocument oDoc = new XPathDocument(filepath); 

      return new MvcHtmlString(GetMenuHtml(oDoc.CreateNavigator(), e, attributes)); 
     } 

     private static string GetMenuHtml(XPathNavigator nav, string e = "ul", object attributes = null) 
     { 

      List<String> item = new List<String>(); 

      XPathNodeIterator nodes = nav.Select("items/item"); 

      TagBuilder holder = new TagBuilder(e); 

      if (attributes != null) 
      { 
       IDictionary<string, object> htmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(attributes); 
       holder.MergeAttributes(htmlAttributes); 
      } 

      while (nodes.MoveNext()) 
      { 

       TagBuilder a = new TagBuilder("a"); 
       TagBuilder span = new TagBuilder("span"); 
       TagBuilder li = new TagBuilder("li"); 

       string url = nodes.Current.GetAttribute("link", string.Empty); 
       string text = nodes.Current.GetAttribute("text", string.Empty); 
       string title = nodes.Current.GetAttribute("title", string.Empty); 

       span.InnerHtml = text; 

       a.MergeAttribute("href", url); 

       if (!String.IsNullOrEmpty(title)) a.MergeAttribute("title", title); 

       a.InnerHtml = span.ToString(); 

       List<String> classes = new List<String>(); 

       if (url == HttpContext.Current.Request.Url.AbsolutePath) 
       { 
        classes.Add("active"); 
       } 

       if (nodes.Count == nodes.CurrentPosition) 
       { 
        classes.Add("last"); 
       } 
       else if (nodes.CurrentPosition == 1) 
       { 
        classes.Add("first"); 
       } 

       if (nodes.Current.HasChildren) 
       { 
        li.InnerHtml = a.ToString() + GetMenuHtml(nodes.Current, e); 

        if (li.InnerHtml.Contains("class=\"active")) 
        { 
         classes.Add("active-trail"); 
        } 

        classes.Add("leaf"); 
       } 
       else 
       { 
        li.InnerHtml = a.ToString(); 
       } 

       if(classes.Count > 0){ 
        li.MergeAttribute("class", string.Join(" ", classes.ToArray())); 
       } 

       item.Add(li.ToString() + "\n"); 

      } 

      holder.InnerHtml = string.Join("", item.ToArray()); 

      return holder.ToString(); 

     } 


    } 

查看:

@Html.Menu("navigation", "ul") 

輸出

<ul> 
    <li class="first active-trail leaf"> 
     <a href="1" title="Some Title"><span>Testing 1</span></a> 
     <ul> 
      <li class="first active-trail leaf"><a href="2"><span>Testing 1-1</span></a> 
       <ul> 
        <li class="active first"><a href="/home/about"><span>Testing 1-1-1</span></a></li> 
        <li><a href="4"><span>Testing 1-1-2</span></a></li> 
        <li class="last"><a href="5"><span>Testing 1-1-3</span></a></li> 
       </ul> 
      </li> 
      <li><a href="6"><span>Testing 1-2</span></a></li> 
      <li class="last"><a href="7"><span>Testing 1-3</span></a></li> 
     </ul> 
    </li> 
    <li><a href="8"><span>Testing 2</span></a></li> 
    <li><a href="9"><span>Testing 3</span></a></li> 
    <li><a href="10"><span>Testing 4</span></a></li> 
    <li><a href="11"><span>Testing 5</span></a></li> 
    <li class="leaf"> 
     <a href="1" title="Some Title"><span>Testing 6</span></a> 
     <ul> 
      <li class="first leaf"><a href="12"><span>Testing 6-1</span></a> 
       <ul> 
        <li class="first"><a href="13"><span>Testing 6-1-1</span></a></li> 
        <li><a href="14"><span>Testing 6-1-2</span></a></li> 
        <li class="last"><a href="15"><span>Testing 6-1-3</span></a></li> 
       </ul> 
      </li> 
      <li><a href="16"><span>Testing 6-2</span></a></li> 
      <li class="last"><a href="17"><span>Testing 6-3</span></a></li> 
     </ul> 
    </li> 
    <li><a href="18"><span>Testing 7</span></a></li> 
    <li class="last leaf"><a href="19"><span>Testing 8</span></a> 
     <ul> 
      <li class="first"><a href="20"><span>Testing 8-1</span></a></li> 
      <li><a href="21"><span>Testing 8-2</span></a></li> 
      <li class="last"><a href="22"><span>Testing 8-3</span></a></li> 
     </ul> 
    </li> 
</ul>