一:TreeView的绑定
CS代码:
为TreeView添加节点#region 为TreeView添加节点
public void bindtvUserGroup()//为树添加一个 "总目录".
{
this.tvUGManage.Nodes.Clear();
TreeNode tnUG = new TreeNode();
tnUG.Text = "F0000根目录";
tnUG.Value = "F0000";
tnUG.Expanded = true;
tvUGManage.Nodes.Add(tnUG);
bindtvParentUserGroup(tnUG);
}
public void bindtvParentUserGroup(TreeNode tnTwo)//在总目录下...添加 "父级树结点"
{
string sqlString = "select FID,FNodeKey,FParentNodeKey,FFunctionName,FFullName,FLayers,FIsLeaf from B_Functions";
DataSet dsBF = new DataSet();
dsBF = B_ZSGC.Select(CnnString, sqlString, "B_Functions");
DataTable dtBF = dsBF.Tables[0];
//this.tvUserGroup.Nodes.Clear();
DataRow[] RowList = dtBF.Select("FParentNodeKey = 'F0000'");
if (RowList.Length > 0)
{
for (int i = 0; i < RowList.Length; i++)
{
TreeNode tnTwoUG = new TreeNode();
tnTwoUG.Text = RowList[i]["FNodeKey"].ToString() + "|" + RowList[i]["FFunctionName"].ToString();
tnTwoUG.Value = RowList[i]["FNodeKey"].ToString();
tnTwoUG.Expanded = false;
tnTwo.ChildNodes.Add(tnTwoUG);//总目录下添加子结点(父级树结点)
bindtvChildUserGroup(tnTwoUG, dtBF);
}
}
}
public void bindtvChildUserGroup(TreeNode tnThre, DataTable dtChild)//在父级树结点下添加 "子结点"
{
DataRow[] RowList = dtChild.Select("FParentNodeKey = '" + tnThre.Value + "'");
if (RowList.Length > 0)
{
for (int j = 0; j < RowList.Length; j++)
{
TreeNode tnThreUG = new TreeNode();
tnThreUG.Text = RowList[j]["FNodeKey"].ToString() + "|" + RowList[j]["FFunctionName"].ToString();
tnThreUG.Value = RowList[j]["FNodeKey"].ToString();
//tnThreUG.Expanded = false;
tnThre.ChildNodes.Add(tnThreUG);
bindtvChildUserGroup(tnThreUG, dtChild); //循环遍历子节点.
}
}
}
#endregion
实现的效果如下图:
数据库中的表样式: 图 1
二:JavaScript实现TreeView中子节点全选
JavaScript:然后为TreeView添加 onclick 事件 即可实现子节点全选的功能.
<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;
checkedState = treeNode.checked;
do
{
obj = obj.parentElement;
} while (obj.tagName != "TABLE")
var parentTreeLevel = obj.rows[0].cells.length;
var parentTreeNode = obj.rows[0].cells[0];
var tables = obj.parentElement.getElementsByTagName("TABLE");
var numTables = tables.length
if (numTables >= 1)
{
for (i=0; i < numTables; i++)
{
if (tables[i] == obj)
{
treeNodeFound = true;
i++;
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];
var inputs = cell.getElementsByTagName("INPUT");
inputs[0].checked = checkedState;
}
else
{
return;
}
}
}
}
}
}
</script>
<asp:TreeView ID="tvUGManage" runat="server" ShowCheckBoxes="All" ShowLines="True"
onclick="client_OnTreeNodeChecked()"></asp:TreeView>
三:储存与解析TreeView中CheckBox的是否选中状态
遍历TreeView存储其是否被选中状态
/**//// <summary>
/// 定义变量,记录描述TreeView中CheckBox的状态.
/// 然后遁环遍历TreeView中的所有结点.如果被选中则为"1",否则为"0".
/// </summary>
string FunctionString = "";
public string tvUserNodesChecked(TreeNode tn)
{
foreach (TreeNode treenode in tn.ChildNodes)
{
if (treenode.Checked)
{
string va = treenode.Value;
FunctionString += "1";
}
else
{
FunctionString += "0";
}
tvUserNodesChecked(treenode);//调用自身函数循环遍历TreeView
}
return FunctionString;//返回FunctionString字符串
}string oFFunctionString = tvUserNodesChecked(tvUGManage.Nodes[0]);
tvUserNodesChecked(tvUGManage.Nodes[0])中的参数为"tvUGManage.Nodes[0]",是因为tvUGManage树的第一个节点是"目录节点".
表示结点的选择状态,在数据库中以FunctionString字段表示. 如图.
解析FunctionString,
解析FunctionString字符串,循环子节点,判断其状态是否被选择
string FunctionNo;
int FunctionNum;
string StrFunction = "";//StrFunction = DataSet.Tables[0].Rows[0]["FFunctionString"].ToString();
//==================================解析FunctionString字符串,判断其状态是否被选择.
if (StrFunction.Trim() != "")
{
foreach (TreeNode node in tvUGManage.Nodes[0].ChildNodes)
{
FunctionNo = functionlib.GetSubString(node.Text, "|", 1);
//functionlib是NetEFO.FunctionLib functionlib = new NetEFO.FunctionLib()中的方法
FunctionNum = Convert.ToInt32(FunctionNo.Substring(1, 4));
if (StrFunction.Substring(FunctionNum - 1, 1) == "1")
{
node.Checked = true;
}
else
{
node.Checked = false;
}
SetFunctionString(node, StrFunction); //遍历循环调用下面的方法
}
}
//==========================================================================
/**//// <summary>
/// 解析FunctionString字符串,循环子节点,判断其状态是否被选择
/// </summary>
/// <param name="RootNode"></param>
/// <param name="strFunctionString"></param>
private void SetFunctionString(TreeNode RootNode, string strFunctionString)
{
string FunctionNo = ""; //根据权限树中的具体设置得到权限字段
int FunctionNum = 0;//设置结点的选择状态
foreach (TreeNode Node in RootNode.ChildNodes)
{
FunctionNo = functionlib.GetSubString(Node.Text, "|", 1);
FunctionNum = Convert.ToInt32(FunctionNo.Substring(1, 4));
if (strFunctionString.Substring(FunctionNum - 1, 1) == "1")
{
Node.Checked = true;
}
else
{
Node.Checked = false;
}
SetFunctionString(Node, strFunctionString);
}
}
从数据库中读取FFunctionString字符串.此解析方法很死板,它只对流程固定的情况下使用才可,也就是说图 1 中数据库表字段 FFunctionName 的流程是已经设定好了的,FFunctionName 的每一步流程依次对应 FFunctionString 的 "1" 或"0",且FNodeKey中的F0001对应的就是FFunctionString 中的第一个1或0,F0002对应的就是FFunctionString 中的第二个1或0,,,依次类推.如果项目中添加一个流程,那么数据库表字段 FNodeKey 必需得按照项目流程重新从F0001 排列.
四: 在选中结点下添加子节点
添加子节点很简单,只需要在数据库中插入一条数据.使 FParentNodeKey的值 == 选中结点的 FNodeKey ,然后在重新绑定TreeView,就可以自动绑定到选中结点下面.
string oFParentNodeKey = this.tvUserGroup.SelectedNode.Value; //TreeView中要添加子节点的结点(作为FParentNodeKey)
string oFFunctionName = this.tbxName.Text.ToString(); //添加子节点的名字
string SqlStr = "insert B_Functions(FNodeKey,FParentNodeKey,FFunctionName)" +
" values('" + oFNodeKey + "','" + oFParentNodeKey + "','" + oFFunctionName + "')";
//oFNodeKey 为 FNodeKey的值