前些天,培训ASP.NET的老师布置了作业,制作商城的一些重要功能,
昨天做了一下其中比较难的商品分类导航类,使用了递归的方法。
ps:使用的是WebForm,希望看到MVC的同学请忽略。
最终效果图:
下面记录一下:
首先是数据库部分,使用的是SQL,在一张叫做Category的表中,设置了以下字段:
[Id] 分类的Id,int,自增长
[Name] 分类的名称,nvarchar(50)
[ParentId] 父类的Id,int
[Link] 链接地址,varchar(max),用于打开链接,也可以通过Get传Id
这里只模拟了一部分数据,从85开始,有6个子类的测试数据,原本是做书店的后台数据库,但我追加了一部分数据,不影响功能的实现。
三层中的Model层,Category类:
1 using System.Collections.Generic; 2
3 namespace Cong.Model 4 { 5 //根节点
6 public class Category 7 { 8 public int Id { get; set; } 9
10 public string Name { get; set; } 11
12 public int ParentId { get; set; } 13
14 public string Link { get; set; } 15 //子类集合
16 public List<Category> Children { get; set; } 17
18 public Category() 19 { 20 this.Children = new List<Category>(); 21 } 22
23 public Category(int id,string name,int parentid,string link) 24 { 25 this.Id = id; 26 this.Name = name; 27 this.ParentId = parentid; 28 this.Link = link; 29 this.Children = new List<Category>(); 30 } 31 } 32 }
三层中的Dao层,CategoryDao类:
1 using Cong.Model; 2 using Cong.Utility; 3 using System.Collections.Generic; 4 using System.Data.SqlClient; 5
6 namespace Cong.Dao 7 { 8 public class CategoryDao 9 { 10 public IEnumerable<Category> GetAllCate() 11 { 12 string sql = "select * from Category"; 13 SqlDataReader reader = SqlHelper.ExecuteReader(sql); 14 if (reader.HasRows) 15 { 16 while (reader.Read()) 17 { 18 Category cate=SqlHelper.MapEntity<Category>(reader); 19 yield return cate; 20 } 21 } 22 } 23 } 24 }
三层中的Bll层,CategoryBll类:
1 using Cong.Dao; 2 using Cong.Model; 3 using System.Collections.Generic; 4 using System.Linq; 5
6 namespace Cong.Bll 7 { 8 public class CategoryBll 9 { 10 CategoryDao cd = new CategoryDao(); 11
12 public Category GetCategorys() 13 { 14 List<Category> list = cd.GetAllCate().ToList(); 15
16 Category root = new Category(); 17 //为节点对象root添加子类,主要是parentId为0的对象
18 root.Children.AddRange(from c in list where c.ParentId == 0 select c); 19 //执行递归方法
20 AddNode(root, list); 21
22 return root; 23 } 24
25 //参数1:传入一个Category类型的节点,这里从root开始, 26 //参数2:第二个参数就是全部分类的集合,用于检索
27 public void AddNode(Category cate, List<Category> list) 28 { 29 for (int i = 0; i < cate.Children.Count; i++) 30 { 31 //临时集合对象,存放parentId与父类的Id相等的对象
32 List<Category> temp = (from c in list where c.ParentId == cate.Children[i].Id select c).ToList(); 33 //加入到Children属性中
34 cate.Children[i].Children.AddRange(temp); 35 //递归,执行方法本体
36 AddNode(cate.Children[i], list); 37 } 38 } 39 } 40 }
Html页面的后台代码:
1 using Cong.Bll; 2 using Cong.Model; 3 using System; 4 using System.Collections.Generic; 5 using System.Linq; 6 using System.Web; 7 using System.Web.UI; 8 using System.Web.UI.WebControls; 9
10 namespace WebApp 11 { 12 public partial class master : System.Web.UI.MasterPage 13 { 14 protected Category root { get; set; } 15
16 protected void Page_Load(object sender, EventArgs e) 17 { 18 CategoryBll cb = new CategoryBll(); 19
20 root = cb.GetCategorys(); 21 } 22 } 23 }
定义了root属性,把从Bll层查找到的数据存到root,便于前端代码输出。
前端Html代码:
1 <div id="menu" class="dropdown hover-toggle">
2 <a class="navbar-brand dropdown-toggle" href="#">全部商品分类 <b class="caret"></b></a>
3 <!--data-toggle="dropdown"-->
4 <div class="clearfix"></div>
5 <ul id="categories" class="dropdown-menu">
6 <%foreach (var i in root.Children) 7 {%>
8 <li>
9 <a href="<%=i.Link %>.aspx"><i class="icon-main icon-<%=i %>"></i><%=i.Name %></a>
10 <ul class="sub-item">
11 <%foreach (var j in i.Children) 12 {%>
13 <li>
14 <a href="<%=j.Link %>.aspx"><%=j.Name %></a>
15 <ul class="sub-item">
16 <%foreach (var k in j.Children) 17 {%>
18 <li><a href="<%=k.Link %>.aspx"><%=k.Name %></a></li>
19 <%} %>
20 </ul>
21 </li>
22 <% } %>
23 </ul>
24 </li>
25
26 <%} %>
27 </ul>
28 </div>
这里使用的是前后台汇编的方法,在后台中已经获取了root节点,通过三层循环,把分类输出到前端。
界面是老师给的前端代码素材,我只是从SQL中查找数据,并且连接到前端。不过这里的前端用的是JQuery和BootStrap,有兴趣的话可以自己制作。
完成。之后还会更新其他部分的代码。