今天比较闲,用C#写了一个无限级分类的例子:
数据库如下:
use master
create database CategoryTest
use CategoryTest
create table Categories(
[Id] int identity primary key not null,
ParentId nvarchar(15) not null,
CategoryName nvarchar(25),
)
insert Categories(ParentId,CategoryName)values(0,'总公司')
insert Categories(ParentId,CategoryName)values(1,'广州公司')
insert Categories(ParentId,CategoryName)values(1,'上海公司')
insert Categories(ParentId,CategoryName)values(1,'汕头公司')
insert Categories(ParentId,CategoryName)values(1,'深圳公司')
insert Categories(ParentId,CategoryName)values(2,'广州销售部')
insert Categories(ParentId,CategoryName)values(2,'广州服务部')
insert Categories(ParentId,CategoryName)values(2,'广州技术部')
insert Categories(ParentId,CategoryName)values(2,'广州行政部')
insert Categories(ParentId,CategoryName)values(8,'广州软件技术部')
insert Categories(ParentId,CategoryName)values(8,'广州硬件技术部')
select * from Categories
一,用递归实现
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Data.SqlClient;
namespace UnlimitCategoryByRecusion
{
/// <summary>
/// 递归实现无限级分类。
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.TreeView tvCategory;
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.Container components = null;
public Form1()
{
InitializeComponent();
}
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows 窗体设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.tvCategory = new System.Windows.Forms.TreeView();
this.SuspendLayout();
//
// tvCategory
//
this.tvCategory.ImageIndex = -1;
this.tvCategory.Location = new System.Drawing.Point(8, 16);
this.tvCategory.Name = "tvCategory";
this.tvCategory.SelectedImageIndex = -1;
this.tvCategory.Size = new System.Drawing.Size(272, 360);
this.tvCategory.TabIndex = 0;
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(292, 398);
this.Controls.Add(this.tvCategory);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
}
#endregion
private void Form1_Load(object sender, System.EventArgs e) {
if(!LoadData()){
return;
}
AddRootNode();
}
private DataTable dt = new DataTable();
private void AddRootNode(){
TreeNode node = null;
for(int i=0;i<dt.Rows.Count;i++){
//寻找根节点
if(dt.Rows[i]["ParentId"].ToString()=="0"){//0代表根节点
node = new TreeNode();
node.Tag=dt.Rows[i]["Id"].ToString();
node.Text=dt.Rows[i]["CategoryName"].ToString();
this.tvCategory.Nodes.Add(node);//加载根节点
AddChildNode(node);//加载支节点
}
}
}
private void AddChildNode(TreeNode currentNode){
TreeNode node = null;
for(int i=0;i<dt.Rows.Count;i++){
if(dt.Rows[i]["ParentId"].ToString()==currentNode.Tag.ToString()){
node = new TreeNode();
node.Tag=dt.Rows[i]["Id"].ToString();
node.Text=dt.Rows[i]["CategoryName"].ToString();
currentNode.Nodes.Add(node);
AddChildNode(node);//递归加载所有节点
}
}
}
/// <summary>
/// 将数据库中分类表加载到DataSet中,避免遍历时经常操作数据库带来的性能下降
/// </summary>
/// <returns>加载成功后返回true</returns>
private bool LoadData(){
try{
using(SqlConnection conn =new SqlConnection("database=CategoryTest;uid=sa;pwd=sa")){
conn.Open();
string sql="select * from Categories";
using(SqlDataAdapter da = new SqlDataAdapter(sql,conn)){
da.Fill(dt);
}
}
return true;
}catch(Exception ex){
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
//MessageBox.Show("读取数据出错");
return false;
}
}
}
}
二,非递归实现
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.Data;
namespace UnlimitCategory {
/// <summary>
/// 功能:树形控件实现无限级分类
/// 作者:林振冲
/// 时间:2008-6-25
/// </summary>
public class Form1 : System.Windows.Forms.Form {
private System.Windows.Forms.TreeView tvCategory;
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.Container components = null;
public Form1() {
//
// Windows 窗体设计器支持所必需的
//
InitializeComponent();
//
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
//
}
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void Dispose( bool disposing ) {
if( disposing ) {
if(components != null) {
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows 窗体设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent() {
this.tvCategory = new System.Windows.Forms.TreeView();
this.SuspendLayout();
//
// tvCategory
//
this.tvCategory.ImageIndex = -1;
this.tvCategory.Location = new System.Drawing.Point(16, 16);
this.tvCategory.Name = "tvCategory";
this.tvCategory.SelectedImageIndex = -1;
this.tvCategory.Size = new System.Drawing.Size(232, 312);
this.tvCategory.TabIndex = 0;
this.tvCategory.BeforeExpand += new System.Windows.Forms.TreeViewCancelEventHandler(this.tvCategory_BeforeExpand);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(292, 350);
this.Controls.Add(this.tvCategory);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
}
#endregion
private DataTable dt = new DataTable();
private void Form1_Load(object sender, System.EventArgs e) {
if(!LoadData()){
return;
}
AddRootNode();
}
//加载根节点前两级节点
private void AddRootNode(){
TreeNode node = null;
for(int i=0;i<dt.Rows.Count;i++){
//寻找根节点
if(dt.Rows[i]["ParentId"].ToString()=="0"){//0代表根节点
node = new TreeNode();
node.Tag=dt.Rows[i]["Id"].ToString();
node.Text=dt.Rows[i]["CategoryName"].ToString();
this.tvCategory.Nodes.Add(node);//加载根节点
AddChildNode(node);//加载支节点
}
}
}
private void AddChildNode(TreeNode currentNode){
TreeNode node = null;
for(int i=0;i<dt.Rows.Count;i++){
if(dt.Rows[i]["ParentId"].ToString()==currentNode.Tag.ToString()){
node = new TreeNode();
node.Tag=dt.Rows[i]["Id"].ToString();
node.Text=dt.Rows[i]["CategoryName"].ToString();
currentNode.Nodes.Add(node);
}
}
}
/// <summary>
/// 将数据库中分类表加载到DataSet中,避免遍历时经常操作数据库带来的性能下降
/// </summary>
/// <returns>加载成功后返回true</returns>
private bool LoadData(){
try{
using(SqlConnection conn =new SqlConnection("database=CategoryTest;uid=sa;pwd=sa")){
conn.Open();
string sql="select * from Categories";
using(SqlDataAdapter da = new SqlDataAdapter(sql,conn)){
da.Fill(dt);
}
}
return true;
}catch(Exception ex){
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
//MessageBox.Show("读取数据出错");
return false;
}
}
private void tvCategory_BeforeExpand(object sender, System.Windows.Forms.TreeViewCancelEventArgs e) {
//遍历所有支节点
//如果e.node为父节点,则将会加载所有支节点下面的叶节点(第三级)
for(int i=0;i<e.Node.Nodes.Count;i++){
//加载支节点下的所有支节点(第三级节点)
AddChildNode(e.Node.Nodes[i]);
}
}
}
}