因为项目里需要在ComboBox里的下拉框里填充树状的选择项,我个人感觉最好还可以做到子结点的伸缩,因此颇费了一些功夫,现在大体做了个总结。
1。第一考虑的是下载现成的控件。
网上找了几个:
1)http://www.codeproject.com/cs/miscctrl/customcombos.asp
2)http://www.codetools.com/cs/miscctrl/ComboBoxTree.asp
第一个不好用,第2个可以用,不过总有问题。每次你在加载了ComboBoxTree的页面添加或修改别的控件后,运行就报错,需要在初始化函数里把一个值人工改为空。而且这个控件只能把每项的name的string值呈现树形,而不能把每个ITEM的text和value一一对应,总之用的不顺手,就放弃了。
test
#region test


/**//// <summary>
/// 获取部门列表
/// </summary>
private void getDeptItem()

...{
PoliceArchives.DbConnect.DBAccess selectDeptDBAccess = new PoliceArchives.DbConnect.DBAccess();
string sqlStr = "SELECT * from dept_tab";
selectDeptDBAccess.SelectDataSetCommand= sqlStr;
selectDeptDBAccess.Open();
deptDS= selectDeptDBAccess.GetDataSet;

AddTree(0,(TreeNode)null);

for(int i=0;i<DeptDS.Tables[0].Rows.Count;i++)

...{
if(DeptDS.Tables[0].Rows[i]["dept_prt_no"].ToString()=="")

...{
this.comboBoxTree1.Nodes.Add(DeptDS.Tables[0].Rows[i]["dept_name"].ToString());
}
}

}


// 递归添加树的节点
public void AddTree(int ParentID,TreeNode pNode)

...{
DataView dvTree = new DataView(deptDS.Tables[0]);
//过滤ParentID,得到当前的所有子节点
dvTree.RowFilter = "[dept_prt_no] = " + ParentID;
foreach(DataRowView Row in dvTree)

...{
if(pNode == null)

...{ //'?添加根节点
TreeNode Node = this.comboBoxTree1.Nodes.Add(Row["dept_name"].ToString());
AddTree(Int32.Parse(Row["dept_no"].ToString()),Node); //再次递归
}
else

...{ //添加当前节点的子节点
TreeNode Node = pNode.Nodes.Add(Row["dept_name"].ToString());
AddTree(Int32.Parse(Row["dept_no"].ToString()),Node); //再次递归
}
}
}

#endregion
2。用treelistView,鼠标单击columnHeader,则把treeListView的高度变高,鼠标落在别的区域,则高度收缩,columnHeader显示的是当前选择项
treelistView里的每个item都可以把text和value分开一一对应,而listView好象不可以。
/**/
/// <summary>
/// 获取部门列表
/// </summary>
private
void
getDeptItem()

...
{
PoliceArchives.DbConnect.DBAccess selectDeptDBAccess = new oliceArchives.DbConnect.DBAccess();
string sqlStr = "SELECT * from dept_tab";
selectDeptDBAccess.SelectDataSetCommand= sqlStr;
selectDeptDBAccess.Open();
deptDS= selectDeptDBAccess.GetDataSet;

DecenTest.Modularization.Controls.TreeListView.TreeListViewItemCollection itemCollection=new DecenTest.Modularization.Controls.TreeListView.TreeListViewItemCollection();

if(deptDS.Tables[0].Rows.Count>0)

...{
this.treeListView1.Visible=true;

循环遍历表一次,把每项添加成TreeListViewItem#region 循环遍历表一次,把每项添加成TreeListViewItem
for(int i=0;i<deptDS.Tables[0].Rows.Count;i++)

...{
string dept_name=deptDS.Tables[0].Rows[i]["dept_name"].ToString();
int dept_prt_no=(int)deptDS.Tables[0].Rows[i]["dept_prt_no"];
int dept_no=(int)deptDS.Tables[0].Rows[i]["dept_no"];
digit=dept_no/100; //位数控制
int m=0; //image索引

while(digit>0)

...{
digit=digit/100;
m++;
}
DecenTest.Modularization.Controls.TreeListView.TreeListViewItem item=new ecenTest.Modularization.Controls.TreeListView.TreeListViewItem(dept_name,m);
itemCollection.Add(item);
item.Tag=dept_no;
if(dept_prt_no==0)

...{
treeListView1.Items.Add(item);
}
}
#endregion

表再遍历一次,每条记录循环一次TreeListViewItem集合,找出该记录的item和父item#region 表再遍历一次,每条记录循环一次TreeListViewItem集合,找出该记录的item和父item
for(int i=0;i<deptDS.Tables[0].Rows.Count;i++)

...{
string dept_name=deptDS.Tables[0].Rows[i]["dept_name"].ToString();
int dept_prt_no=(int)deptDS.Tables[0].Rows[i]["dept_prt_no"];
int dept_no=(int)deptDS.Tables[0].Rows[i]["dept_no"];
DecenTest.Modularization.Controls.TreeListView.TreeListViewItem childItem=null;
DecenTest.Modularization.Controls.TreeListView.TreeListViewItem parentItem=null;
if(dept_prt_no!=0)

...{
foreach(DecenTest.Modularization.Controls.TreeListView.TreeListViewItem item in itemCollection)

...{
if((int)item.Tag==dept_no)

...{
childItem=item;
}
if((int)item.Tag==dept_prt_no)

...{
parentItem=item;
}
}
parentItem.Items.Add(childItem);
}
}
}
---用treeView实现:
test
#region test 用treeView实现:
System.Windows.Forms.TreeView itemCollection=new TreeView();

if(deptDS.Tables[0].Rows.Count>0)

...{

循环遍历表一次,把每项添加成TreeListViewItem#region 循环遍历表一次,把每项添加成TreeListViewItem
for(int i=0;i<deptDS.Tables[0].Rows.Count;i++)

...{
string dept_name=deptDS.Tables[0].Rows[i]["dept_name"].ToString();
int dept_prt_no=(int)deptDS.Tables[0].Rows[i]["dept_prt_no"];
int dept_no=(int)deptDS.Tables[0].Rows[i]["dept_no"];
int digit=dept_no/100; //位数控制
int m=0; //image索引

while(digit>0)

...{
digit=digit/100;
m++;
}
System.Windows.Forms.TreeNode item=new TreeNode();
itemCollection.Nodes.Add(item);
item.Tag=dept_no;
item.Text=dept_name;
if(dept_prt_no==0)

...{
this.treeView1.Nodes.Add(new TreeNode(dept_name));
this.treeView1.ExpandAll();
}
}
#endregion

表再遍历一次,每条记录循环一次TreeListViewItem集合,找出该记录的item和父item#region 表再遍历一次,每条记录循环一次TreeListViewItem集合,找出该记录的item和父item
for(int i=0;i<deptDS.Tables[0].Rows.Count;i++)

...{
string dept_name=deptDS.Tables[0].Rows[i]["dept_name"].ToString();
int dept_prt_no=(int)deptDS.Tables[0].Rows[i]["dept_prt_no"];
int dept_no=(int)deptDS.Tables[0].Rows[i]["dept_no"];
System.Windows.Forms.TreeNode childItem=null;
System.Windows.Forms.TreeNode parentItem=null;
if(dept_prt_no!=0)

...{
foreach(System.Windows.Forms.TreeNode item in itemCollection.Nodes)

...{
if((int)item.Tag==dept_no)

...{
childItem=item;
}
if((int)item.Tag==dept_prt_no)

...{
parentItem=item;
}
}
parentItem.Nodes.Add(childItem);
}
}
#endregion
}
3。用textBox+checkBox(或者button)+listview的方法
具体就是用鼠标事件控制落在checkBox(button)的区域,一旦鼠标释放或点击,则将listView隐藏或显示,其中listView为树状显示。
用listView获取部门列表
#region 用listView获取部门列表

/**//// <summary>
/// 获取部门列表
/// </summary>
private void getDeptItem()

...{
PoliceArchives.DbConnect.DBAccess selectDeptDBAccess = new PoliceArchives.DbConnect.DBAccess();
string sqlStr = "SELECT * from dept_tab";
selectDeptDBAccess.SelectDataSetCommand= sqlStr;
selectDeptDBAccess.Open();
deptDS= selectDeptDBAccess.GetDataSet;

AddTree(0,(TreeNode)null);
}

// 递归添加树的节点
public void AddTree(int ParentID,TreeNode pNode)

...{
DataView dvTree = new DataView(deptDS.Tables[0]);
//过滤ParentID,得到当前的所有子节点
dvTree.RowFilter = "[dept_prt_no] = " + ParentID;
foreach(DataRowView Row in dvTree)

...{
if(pNode == null)

...{ //添加根节点
TreeNode Node = this.treeView1.Nodes.Add(Row["dept_name"].ToString());
Node.Tag=Row["dept_no"].ToString();
AddTree(Int32.Parse(Row["dept_no"].ToString()),Node); //再次递归
}
else

...{ //添加当前节点的子节点
TreeNode Node = pNode.Nodes.Add(Row["dept_name"].ToString());
Node.Tag=Row["dept_no"].ToString();
AddTree(Int32.Parse(Row["dept_no"].ToString()),Node); //再次递归
}
}
}

private void textBox2_MouseEnter(object sender, System.EventArgs e)

...{
this.treeView1.Visible=true;
this.treeView1.BringToFront(); //把控件置于顶层
}

private void treeView1_MouseLeave(object sender, System.EventArgs e)

...{
this.treeView1.Visible=false;;
}

private void treeView1_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)

...{
this.textBox2.Text=this.treeView1.SelectedNode.Text;

}

private void checkBox1_CheckedChanged(object sender, System.EventArgs e)

...{
if(this.checkBox1.Checked==true)

...{
this.treeView1.Visible=true;
this.treeView1.BringToFront(); //把控件置于顶层
}
else

...{
this.treeView1.Visible=false;
}
}

#endregion
4。也是最后采用的方法,就是ComboBox+存储过程,即在存储过程里重新排列所有ITEM,让其成为树形,再显示出来。本来想用SQL自定义函数排序,搞了很久未果,最终还是用存储过程实现。这将在之后的文章里说明。这种方法是本质解决,虽然不能象treeView一样收缩展开,但是前几种方法感觉都是敷衍的障眼法。