前几天头说让我帮忙解决一个问题,写一个控件的绑定,其实就是一个的数据源绑定,的每个节点上要加CheckBox,当选中父节点时要选中子节点,但是只返回最底层节点的value和text。最后出来效果图如下:
递归实现的绑定。CS代码如下:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
this.stfTree.Attributes.Add(“onclick”, “return client_OnTreeNodeChecked();”);
TreeNode node = new TreeNode(“公司”, “0″);
LoadChildNode(node, test(), “parent_dept_id=0 “, “dept_id”, “dept_name”);
this.stfTree.Nodes.Add(node);
}
}
#region stffTree
private DataTable test()
{
DataTable rtn = new DataTable();
rtn.Columns.Add(“parent_dept_id”, typeof(String));
rtn.Columns.Add(“parent_dept_name”, typeof(String));
rtn.Columns.Add(“dept_id”, typeof(String));
rtn.Columns.Add(“dept_name”, typeof(String));
rtn.Columns.Add(“stn_id”, typeof(String));
rtn.Columns.Add(“stn_name”, typeof(String));
rtn.Columns.Add(“stf_id”, typeof(String));
rtn.Columns.Add(“stf_name”, typeof(String));
DataRow subRow = rtn.NewRow();
subRow["parent_dept_id"] = “0″;
subRow["parent_dept_name"] = “全部”;
subRow["dept_id"] = “01″;
subRow["dept_name"] = “部门1″;
subRow["stn_id"] = “001″;
subRow["stn_name"] = “岗位1″;
subRow["stf_id"] = “0001″;
subRow["stf_name"] = “员工1″;
rtn.Rows.Add(subRow);
DataRow subRow1 = rtn.NewRow();
subRow1["parent_dept_id"] = “0″;
subRow1["parent_dept_name"] = “全部”;
subRow1["dept_id"] = “02″;
subRow1["dept_name"] = “部门2″;
subRow1["stn_id"] = “002″;
subRow1["stn_name"] = “岗位2″;
subRow1["stf_id"] = “0002″;
subRow1["stf_name"] = “员工2″;
rtn.Rows.Add(subRow1);
DataRow subRow2 = rtn.NewRow();
subRow2["parent_dept_id"] = “01″;
subRow2["parent_dept_name"] = “全部”;
subRow2["dept_id"] = “03″;
subRow2["dept_name"] = “部门11″;
subRow2["stn_id"] = “003″;
subRow2["stn_name"] = “岗位3″;
subRow2["stf_id"] = “0003″;
subRow2["stf_name"] = “员工3″;
rtn.Rows.Add(subRow2);
DataRow subRow3 = rtn.NewRow();
subRow3["parent_dept_id"] = “01″;
subRow3["parent_dept_name"] = “全部”;
subRow3["dept_id"] = “03″;
subRow3["dept_name"] = “部门11″;
subRow3["stn_id"] = “003″;
subRow3["stn_name"] = “岗位3″;
subRow3["stf_id"] = “0004″;
subRow3["stf_name"] = “员工4″;
rtn.Rows.Add(subRow3);
DataRow[] dr = rtn.Select(“parent_dept_id=0″ );
dr = rtn.Select(“dept_id=01″);
return rtn;
}
/*
* dt 四个字段 stf_id,stn_id,dept_id,parent_dept_id
* 先查询parent_dept_id添加到Hashtable key=parent_dept_id; value=parent_dept_name
* 遍历Hashtable,根据 parent_dept_id,查找dept_id添加到Hashtable key=dept_id; value=dept_name
* 遍历Hashtable,根据 dept_id,查找stn_id添加到Hashtable key=stn_id; value=stn_name
* 遍历Hashtable,根据 stn_id,查找stf_id添加到newNode
**/
/// <summary>
/// 递归填充treeView
/// </summary>
/// <param name=”node”>父节点</param>
/// <param name=”dt”>dt</param>
/// <param name=”condition”>查询条件 如parent_dept_id=”0″</param>
/// <param name=”key”>stf_id,stn_id,dept_id,parent_dept_id</param>
/// <param name=”value”>stf_id,stn_id,dept_id,parent_dept_id对应显示</param>
private int LoadChildNode(TreeNode node, DataTable dt, string condition, string key, string value)
{
IDictionary isFilled = new Hashtable();
//TODO:填充Hashtable
DataRow[] dr = dt.Select(condition);
for (int i = 0; i < dr.Length; i++)
{
string id = dr[i][key].ToString();
if (!isFilled.Contains(id))
{
string name = dr[i][value].ToString();
isFilled.Add(id, “”);
TreeNode subNode = new TreeNode(name, id);
string cond = condition.Split(‘=’)[0];
if (cond == “parent_dept_id”)
{
LoadChildNode(subNode, dt, “parent_dept_id=” + id + ” “, key, value) ;
LoadChildNode(subNode, dt, “dept_id=” + id + ” “, “stn_id”, “stn_name”);
}
else if (cond == “dept_id”)
{
LoadChildNode(subNode, dt, “stn_id=” + id + ” “, “stf_id”, “stf_name”);
}
node.ChildNodes.Add(subNode);
}
}
return dr.Length;
}
protected void on_click(object sender, EventArgs e)
{
}
#endregion
主要是JS上比较复杂,要研究过TreeView生成完的HTML代码,里面DIV和Table嵌套使用的结构。
<script language=”javascript” type=”text/javascript”>
function client_OnTreeNodeChecked()
{
var obj = window.event.srcElement;
// 当前触发事件对象
var treeNodeFound = false;
// 后面解释
var checkedState;
// 选中状态
if (obj.tagName == “INPUT” && obj.type == “checkbox”)
{
var treeNode = obj;
// 当前CheckBox
checkedState = treeNode.checked;
// 当前CheckBox选中状态
do
{
obj = obj.parentElement;
}
while (obj.tagName != “TABLE”)
// 找到当前CheckBox所在的Table
var parentTreeLevel = obj.rows[0].cells.length;
// 当前节点所属层次
// 生成的HTML代码中为了收缩,每加一层加一个TD
// TD的个数就是节点层次数
var parentTreeNode = obj.rows[0].cells[0];
// 无用处
var tables = obj.parentElement.getElementsByTagName(“TABLE”);
// 当前CheckBox所在的Table隶属的DIV下的所有Table,也就免除了递归
var numTables = tables.length
if (numTables >= 1)
{
for (i=0; i < numTables; i++)
{
if (tables[i] == obj)
{// 当前CheckBox所在的Table是其隶属的DIV下有多个Table
// 但是当前CheckBox所在节点的子节点所在table的Id均比当前节点大
// 只有先找到当前节点才去置其子节点的Checked属性
treeNodeFound = true;
// 找到当前CheckBox所在的Table
i++;
// 当前CheckBox不用处理
if (i == numTables)
{// 如果没有字节点结束
return;
}
}
if (treeNodeFound == true)
{
var childTreeLevel = tables[i].rows[0].cells.length;
if (childTreeLevel > parentTreeLevel)
{
var cell = tables[i].rows[0].cells[childTreeLevel - 1];
// 数组从0开始计数,CheckBox在最后一个Td中
var inputs = cell.getElementsByTagName(“INPUT”);
inputs[0].checked = checkedState;
// 置CheckBox状态
}
else
{
return;
}
}
}
}
}
}
</script>
<script language=”javascript” type=”text/javascript”>
function Result(v_stf_id,v_stf_name)
{
this.stf_id = v_stf_id;
this.stf_name=v_stf_name;
}
function GetSelecteStf()
{
var rtn=new Array();
var obj=document.getElementById(“stfTreen0Nodes”);
var parentTreeLevel=0 ;
// 当前节点所属层次
// 生成的HTML代码中为了收缩,每加一层加一个TD
// TD的个数就是节点层次数
var tables = obj.parentElement.getElementsByTagName(“TABLE”);
// 当前CheckBox所在的Table隶属的DIV下的所有Table,也就免除了递归
var numTables = tables.length
if (numTables >= 1)
{
for (i=0; i < numTables; i++)
{
var currentTreeLevel= tables[i].rows[0].cells.length;
var cell = tables[i].rows[0].cells[currentTreeLevel - 1];
var inputs = cell.getElementsByTagName(“INPUT”);
if(inputs[0].checked )
{// 父节点选中
if(i+1 < numTables)
{// 跟下一个节点的深度比较
// 如果这个节点深度大于等于下一个节点深度
// 那么这个节点就是最底层节点
var nextTreeLevel = tables[i+1].rows[0].cells.length;
if(currentTreeLevel >= nextTreeLevel)
{// 该节点是最底层节点
var herf= cell.getElementsByTagName(“A”);
rtn.push(new Result(GetNodeValue(herf[0]),herf[0].innerHTML));
}
}
else
{// 这个节点本身就是最后一个节点,肯定是最底层节点
var herf= cell.getElementsByTagName(“A”);
rtn.push(new Result(GetNodeValue(herf[0]),herf[0].innerHTML));
}
}
}
}
return rtn;
}
function GetNodeValue(obj)
{
var content=obj;
content =”#”+content;
var ids= content.match(/\d+/g);
return ids[ids.length-1];
}
</script>


3 Comments
leo
on 2009年01月14日 at 10:37.
很好很强大!
KattyBlackyard
on 2009年06月15日 at 23:45.
I really like your post. Does it copyright protected?
Felix
on 2009年06月17日 at 20:14.
about this post , i find lots of references such as MSDN
and got source code from code.google.com ,so i have no idea that it copyright protected or not!
but other posts of my blog just my own opinion that is may copyright protected!