C# 使用c语言的递归菜单生成器#

C# 使用c语言的递归菜单生成器#,c#,recursion,C#,Recursion,尝试使用c#构建递归html菜单。我需要的html结构如下所示: <ul> <li>Office</li> <li>Home <ul> <li>Beds</li> <li>Desks</li> </ul> </li> <li>Outdoor <ul>

尝试使用c#构建递归html菜单。我需要的html结构如下所示:

<ul>
   <li>Office</li>
   <li>Home
      <ul>
         <li>Beds</li>
         <li>Desks</li>
      </ul>
   </li>
   <li>Outdoor
      <ul>
         <li>Children
            <ul>
               <li>Playsets</li>
            </ul>
         </li>
      </ul>
   </li>
</ul>
  • 办公室
    • 办公桌
  • 户外
    • 孩子们
      • 剧集

结构可能会发生明显变化,因为它是动态的。目前,我正在使用HtmlGeneric控件,即ul、li和添加控件,但不确定如何将其转换为有效的递归函数。

我不确定保持字符串层次结构的结构是什么,但假设您有某种方法可以根据需要获取每个字符串的子字符串(例如,您可以从“家”获得“床”和“桌子”)

首先,我将标记声明为常量:

 public const string OPEN_LIST_TAG = "<ul>";
 public const string CLOSE_LIST_TAG = "</ul>";
 public const string OPEN_LIST_ITEM_TAG = "<li>";
 public const string CLOSE_LIST_ITEM_TAG = "</li>";
public const string OPEN_LIST_TAG=“
    ”; public const string CLOSE_LIST_TAG=“
”; public const string OPEN_LIST_ITEM_TAG=“
  • ”; public const string CLOSE_LIST_ITEM_TAG=“
  • ”;
    然后,我将使用类似字符串生成器的东西创建一个递归方法:

    /// <summary>
    /// Adds another level of HTML list and list items to a string
    /// </summary>
    /// <param name="str">The string to add</param>
    /// <param name="liStrings">The list of strings at this level to add</param>
    /// <param name="iTabIndex">The current number of tabs indented from the left</param>
    public void GenerateHTML( System.Text.StringBuilder str, List<string> liStrings, int iTabIndex) {
       //add tabs to start of string
       this.AddTabs(str, iTabIndex);
    
       //append opening list tag
       str.AppendLine(OPEN_LIST_TAG);
    
       foreach (string strParent in liStrings) {
          //add tabs for list item
          this.AddTabs(str, iTabIndex + 1);
    
          //if there are child strings for this string then loop through them recursively
          if (this.GetChildStrings(strParent).Count > 0) {
             str.AppendLine(OPEN_LIST_ITEM_TAG + strParent);
             GenerateHTML(str, this.GetChildStrings(strParent), iTabIndex + 2);
    
             //add tabs for closing list item tag
             this.AddTabs(str, iTabIndex + 1);
             str.AppendLine(CLOSE_LIST_ITEM_TAG);
          }
          else {
             //append opening and closing list item tags
             str.AppendLine(OPEN_LIST_ITEM_TAG + strParent + CLOSE_LIST_ITEM_TAG);
          }
       }
    
       //add tabs for closing list tag
       this.AddTabs(str, iTabIndex);
       //append closing list tag
       str.AppendLine(CLOSE_LIST_TAG);
    }
    
    //
    ///将另一级别的HTML列表和列表项添加到字符串中
    /// 
    ///要添加的字符串
    ///此级别要添加的字符串列表
    ///从左侧缩进的当前选项卡数
    public void GenerateHTML(System.Text.StringBuilder str,List liStrings,int-iTabIndex){
    //将选项卡添加到字符串的开头
    这是AddTabs(str,iTabIndex);
    //附加开始列表标记
    str.AppendLine(打开列表标签);
    foreach(liStrings中的字符串strParent){
    //为列表项添加选项卡
    这个.AddTabs(str,iTabIndex+1);
    //如果此字符串有子字符串,则递归地遍历它们
    if(this.GetChildStrings(strParent.Count>0){
    str.AppendLine(打开列表项标记+strParent);
    GenerateHTML(str,this.GetChildStrings(strParent),iTabIndex+2);
    //为关闭列表项标记添加选项卡
    这个.AddTabs(str,iTabIndex+1);
    str.AppendLine(关闭列表项标记);
    }
    否则{
    //附加开始和结束列表项标记
    str.AppendLine(打开列表项标记+strParent+关闭列表项标记);
    }
    }
    //为关闭列表标记添加选项卡
    这是AddTabs(str,iTabIndex);
    //附加结束列表标记
    str.AppendLine(关闭列表标签);
    }
    
    并将选项卡分离出来,添加到单独的方法中:

    /// <summary>
    /// Appends a number of tabs to the string builder
    /// </summary>
    /// <param name="str">The string builder to append to</param>
    /// <param name="iTabIndex">The number of tabs to append to</param>
    public void AddTabs(System.Text.StringBuilder str, int iTabIndex) {
       for (int i = 0; i <= iTabIndex; i++) {
          str.Append("\t");
       }
    }
    
    //
    ///将多个选项卡附加到字符串生成器
    /// 
    ///要附加到的字符串生成器
    ///要附加到的选项卡数
    public void AddTabs(System.Text.StringBuilder str,int-iTabIndex){
    
    对于(inti=0;i这样的列表,唯一递归的是数据结构,这是一个很好的数据结构开源库

    另外,我建议在这个问题中使用

    如果您想采用自己的方法创建一个服务器控件,那么下面的类就可以了

    public class MenuTree : Control
    {
       public string MenuText {get; set;}
       public List<MenuTree> Children {get; set;}
    
       public override void Render(HTMLTextWriter writer)
       {
          writer.RenderBeginTag(HtmlTextWriterTag.Ul);
          writer.RenderBeginTag(HtmlTextWriterTag.Li);
          writer.RenderBeginTag(MenuText);
          writer.RenderEndTag();
          foreach (MenuTree m in Children)
          {
             m.Render();
          }
          writer.RenderEndTag();
       }
    
    
    }
    
    公共类菜单ree:Control
    {
    公共字符串MenuText{get;set;}
    公共列表子项{get;set;}
    公共覆盖无效呈现(HTMLTextWriter)
    {
    writer.RenderBeginTag(htmltextwittertag.Ul);
    writer.RenderBeginTag(htmltextwittertag.Li);
    writer.RenderBeginTag(MenuText);
    writer.renderndtag();
    foreach(儿童的MenuTree m)
    {
    m、 Render();
    }
    writer.renderndtag();
    }
    }
    
    这个话题有点老,但它应该有一个正确的答案

    在我的示例中,传入节点包含一个包含子元素的子属性

    private HtmlGenericControl RenderMenu(Nodes nodes)
    {
        if (nodes == null)
            return null;
    
        var ul = new HtmlGenericControl("ul");
    
        foreach (Node node in nodes)
        {
            var li = new HtmlGenericControl("li");
            li.InnerText = node.Name;
    
            if(node.Children != null)
            {
                li.Controls.Add(RenderMenu(node.Children));
            }
    
            ul.Controls.Add(li);
        }
    
        return ul;
    }
    

    请添加任务单上的代码。您使用什么结构来保存字符串(即“家”、“床”、“桌子”等)?