使用c#作为ul列表而不是Asp.net菜单控件从数据表生成嵌套菜单

时间:2013-01-03 11:14:27

标签: c# asp.net html-lists

我需要生成一个自定义菜单,其子菜单使用DataTable

中的列表ul

以下是包含虚拟数据的数据库示例和示例HTML ul列表。

PID         MENU                 Handler                  PageLangID  ParentID    IssueID     CatID       MenuPosition
----------- -------------------- ------------------------ ----------- ----------- ----------- ----------- ------------

6           Business             Category.aspx    1           6           1           16          1
6           Culture              Category.aspx    1           6           1           3           1
6           Economy              Category.aspx    1           6           1           2           1
6           Finance              Category.aspx    1           6           1           19          1
6           Infrastructure       Category.aspx    1           6           1           17          1
6           Lifestyle            Category.aspx    1           6           1           20          1
6           Others               Category.aspx    1           6           1           21          1
6           People               Category.aspx    1           6           1           7           1
6           Politics             Category.aspx    1           6           1           1           1
6           Sports               Category.aspx    1           6           1           4           1
12          1002                  Default.aspx             1           12          3           1           1
12          1003                  Default.aspx             1           12          4           1           1
12          1006                  Default.aspx             1           12          1           1           1
12          1009                  Default.aspx             1           12          5           1           1
1           Home                 Default.aspx             1           0           1           1           10
11          Video                Videos.aspx              1           10          1           1           10
2           About Us             Page.aspx                1           0           1           1           20
5           Articles             Articles.aspx            1           0           1           1           20
6           Categories           Category.aspx    1           0           

期望的HTML输出

<div id="nav-wrapper">
<ul id="nav" class="dropdown dropdown-linear"  >
    <li><span class="dir"><a href="./">Home</a></span></li>
    <li ><span class="dir"><a href="ultimate.linear.html">About Us</a></span>
        <ul >
            <li><a href="./">History</a></li>
            <li><a href="./">Our Vision</a></li>
            <li><a href="./">The Team</a></li>
            <li><a href="./">Clients</a></li>
            <li><a href="./">Testimonials</a></li>
            <li><a href="./">Press</a></li>
            <li><a href="./">FAQs</a></li>
        </ul>
    </li>

    <li class="active" ><span class="dir"><a href="ultimate.linear-active.html">Categories</a></span>
        <ul>
            <li><a href="./">Politics</a></li>
            <li><a href="./">Economy</a></li>
            <li><a href="./">Finance</a></li>
            <li><a href="./">Business</a></li>
            <li><a href="./">Group News</a></li>
            <li><a href="./">Culture</a></li>
            <li><a href="./">Lifestyle</a></li>
            <li><a href="./">Sports</a></li>
            <li><a href="./">Infrastructure</a></li>
            <li><a href="./">Book Review</a></li>   
            <li><a href="./">Others</a></li>                
        </ul>
    </li>
</ul>
</div> 

我不想使用嵌套的转发器控件。我很感激我可以使用的示例代码。

更新:此代码不起作用,我肯定做错了什么

protected void Page_Load(object sender, EventArgs e)
{

    DataSet ds = new DataSet();
    ds = DataProvider.Connect_Select(strSql);
     DataTable dt = ds.Tables[0];

    //dt.Select("ParentID == 0") ;
    var s = GenerateUL(dt.Select("ParentID == 0"));
    Response.Write(s);

}


private string GenerateUL(var menus)
{
    var sb = new StringBuilder();

    sb.AppendLine("<ul>");
    foreach (var menu in menus)
    {
        if (menu.Menus.Any())
        {
            sb.AppendLine("<li>" + menu.Text);
            sb.Append(GenerateUL(menu.Menus.AsQueryable()));
            sb.AppendLine("</li>");
        }
        else
            sb.AppendLine("<li>" + menu.Text + "</li>");
    }
    sb.AppendLine("</ul>");

    return sb.ToString();
}

基于DANI解决方案的最新更新

它的数据样本似乎运行正常但是当我将它与我的实际数据一起使用时,它生成的StackOverflowException未处理。

以下是错误的屏幕截图。 enter image description here

当进入无限循环时产生错误PID=6我上面显示的实际数据有23条记录&amp;是来自不同表格的UNION的结果,这就是我在表格中有多行的原因PID=6我担心它在pid=12 protected void Page_Load(object sender, EventArgs e) { string strSql = "SELECT DISTINCT PID, MENU, Handler,PageLangID, ParentID,IssueID, CatID,MenuPosition FROM MENUTABLE "; DataSet ds = new DataSet(); ds = DataProvider.Connect_Select(strSql); DataTable table = ds.Tables[0]; DataRow[] parentMenus = table.Select("ParentId = 0"); var sb = new StringBuilder(); string unorderedList = GenerateUL(parentMenus, table, sb); } private string GenerateUL(DataRow[] menu, DataTable table, StringBuilder sb) { sb.AppendLine("<ul>"); try { if (menu.Length > 0) { foreach (DataRow dr in menu) { ctr = ctr + 1; string handler = dr["Handler"].ToString(); string menuText = dr["MENU"].ToString(); string line = String.Format(@"<li><a href=""{0}"">{1}</a>", handler, menuText); sb.Append(line); string pid = dr["PID"].ToString(); DataRow[] subMenu = table.Select(String.Format("ParentId = {0}", pid)); if (subMenu.Length > 0) { var subMenuBuilder = new StringBuilder(); sb.Append(GenerateUL(subMenu, table, subMenuBuilder)); } sb.Append("</li>"); } } } catch (Exception ex) { } sb.Append("</ul>"); return sb.ToString(); } 也会这样做。

即使我发现异常,我的网站仍因此崩溃......

最新代码

PID         MENU                 Handler                  PageLangID  ParentID    IssueID     CatID       MenuPosition
----------- -------------------- ------------------------ ----------- ----------- ----------- ----------- ------------
1           Home                 Default.aspx             1           0           1           1           10
2           About Us             Page.aspx                1           0           1           1           20
3           News                 News.aspx                1           0           1           1           30
5           Articles             Articles.aspx            1           0           1           1           20
6           Categories           Category.aspx    1           0           1           1           25

更新:当我更改我的查询以获得下面的结果时,它可以正常工作,但最好让它在问题中首先显示的实际数据上工作。

{{1}}

1 个答案:

答案 0 :(得分:10)

我在我这边创建了一个稍微简单的表结构,因为我们只需要以下列,例如:

  1. PID
  2. MENU
  3. 处理程序
  4. PARENTID
  5. 示例数据:

    正如您在本示例中所看到的,我们对Product有一个3向深层次结构,其余项目没有子项。

    enter image description here

    代码背后:

    以下代码执行以下操作:

    1. 首先获取所有没有父母的项目并开始循环使用
    2. 检查项是否是任何节点的父项,并以递归方式获取其子项。

      protected void Page_Load(object sender, EventArgs e)
      {
          DataSet ds = new DataSet();
          ds = DataProvider.Connect_Select("SELECT * FROM Menu");
          DataTable table = ds.Tables[0];
          DataRow[] parentMenus = table.Select("ParentId = 0");
      
          var sb = new StringBuilder();
          string unorderedList = GenerateUL(parentMenus, table,sb);
          Response.Write(unorderedList);
      }
      
      private string GenerateUL(DataRow[] menu,DataTable table,StringBuilder sb)
      {
          sb.AppendLine("<ul>");
      
          if (menu.Length > 0)
          {
              foreach (DataRow dr in menu)
              {
                  string handler = dr["Handler"].ToString();
                  string menuText = dr["MENU"].ToString();
                  string line = String.Format(@"<li><a href=""{0}"">{1}</a>",handler,menuText);
                  sb.Append(line);
      
                  string pid = dr["PID"].ToString();
      
                  DataRow[]subMenu = table.Select(String.Format("ParentId = {0}", pid));
                  if (subMenu.Length > 0)
                  {
                      var subMenuBuilder = new StringBuilder();
                      sb.Append(GenerateUL(subMenu, table, subMenuBuilder));
                  }
                  sb.Append("</li>");
              }
          }
      
          sb.Append("</ul>");
          return sb.ToString();
      }
      
    3. 最终结果:

      enter image description here

      修改

      问题在于代码根据ParentID构造菜单,对于ID = 6,ParentID也恰好是6.所以6个调用6,我们有一个无限循环,很棒。

      现在我们知道问题是什么,我们可以进行简单的检查,只有ParentId != PID递归地构造子菜单,这里是更新的代码:

      private string GenerateUL(DataRow[] menu, DataTable table, StringBuilder sb)
      {
          sb.AppendLine("<ul>");
      
          if (menu.Length > 0)
          {
              foreach (DataRow dr in menu)
              {
                  string handler = dr["Handler"].ToString();
                  string menuText = dr["MENU"].ToString();
                  string line = String.Format(@"<li><a href=""{0}"">{1}</a>", handler, menuText);
                  sb.Append(line);
      
                  string pid = dr["PID"].ToString();
                  string parentId = dr["ParentId"].ToString();
      
                  DataRow[] subMenu = table.Select(String.Format("ParentId = {0}", pid));
                  if (subMenu.Length > 0 && !pid.Equals(parentId))
                  {
                      var subMenuBuilder = new StringBuilder();
                      sb.Append(GenerateUL(subMenu, table, subMenuBuilder));
                  }
                  sb.Append("</li>");
              }
          }
          sb.Append("</ul>");
          return sb.ToString();
      }
      

      我认为重要的是通过在调试器中单步执行它来实际理解这段代码是如何工作的,这样一来,如果出现任何其他问题,你就可以改变它。