代码目标:以树型表达组织单位和下属用户的层次结构关系,并允许通过CHECKBOX多选组织和/或用户
其他需求:组织单位总数约三千个,用户总数约四万人。
环境:.NET Framework 1.1
IDE:Visual Studio.NET 2003
1. OrgXMLCreator.aspx 是一个空白的 Web 窗体
OrgXMLCreator.aspx.cs 目的是生成组织节点,内容片段如下:
private
void
Page_Load(
object
sender, System.EventArgs e)
{
string
orgID
=
Request.QueryString[
"
oid
"
].ToString().Trim();
Response.ContentEncoding
=
System.Text.UTF8Encoding.UTF8;
if
(orgID.Length
>
0
)
{
Response.Write (CreateXml(orgID));
}
Response.End();
}
public
string
CreateXml(
string
orgID)
{
StringBuilder sb
=
new
StringBuilder();
//
sb.Append("<?xml version=\"1.0\" encoding=\"gb2312\"?>\r\n");
sb.Append(
"
<TREENODES>\r\n
"
);
if
(orgID
!=
"
0
"
)
{
//
======== inner node ================
//
set attribute NodeData to userid
sb.Append(
"
<TreeNode NodeData=\
""
);
sb.Append(
"
0
"
);
//
set attribute Text to zhname
sb.Append(
"
\
"
Text
=
\
""
);
sb.Append(
"
直属用户
"
);
sb.Append(
"
\
"
"
);
//
set other attributes
sb.Append(
"
Checkbox=\
"
false
\
"
Type=\
"
None\
"
Expanded=\
"
true
\
"
"
);
sb.Append(
"
TreeNodeSrc=\
"
UserXMLCreator.aspx
?
oid
=
"
); // 直属用户的立即异步加载
sb.Append(orgID);
sb.Append(
"
\
"
"
);
sb.Append(
"
>\r\n
"
);
sb.Append(
"
</TreeNode>
"
);
//
====================================
}
DataTable dt
=
new
DataTable();
dt
=
DataProvider.Instance.GetChildOrg(orgID).Tables[
0
];
sb.Append(CreateList(dt));
sb.Append(
"
</TREENODES>
"
);
return
sb.ToString();
}
protected
string
CreateList(DataTable dt)
{
StringBuilder sb
=
new
StringBuilder();
try
{
DataRow[] drs
=
dt.Select(
"
1=1
"
,
"
Showorder
"
);
foreach
(DataRow dr
in
drs)
{
sb.Append(CreateElement(dr));
}
return
sb.ToString();
}
catch
{
return
""
;
}
}
protected
string
CreateElement(DataRow dr)
{
StringBuilder sb
=
new
StringBuilder();
string
id
=
dr[
"
id
"
].ToString();
//
set attribute NodeData to userid
sb.Append(
"
<TreeNode NodeData=\
""
);
sb.Append(id);
//
set attribute Text to zhname
sb.Append(
"
\
"
Text
=
\
""
);
sb.Append(dr[
"
name
"
].ToString());
sb.Append(
"
\
"
"
);
//
set other attributes
if
(dr[
"
hasPermission
"
].ToString().Equals(
"
1
"
))
{
sb.Append(
"
Checkbox=\
"
true
\
"
Type=\
"
OU\
"
Expanded=\
"
false
\
"
"
);
}
else
{
sb.Append(
"
Checkbox=\
"
false
\
"
Type=\
"
OU\
"
Expanded=\
"
false
\
"
"
);
}
sb.Append(
"
TreeNodeSrc=\
"
OrgXMLCreator.aspx
?
oid
=
"
); // 子组织的延迟异步加载
sb.Append(id);
sb.Append(
"
\
"
"
);
sb.Append(
"
>\r\n
"
);
sb.Append(
"
</TreeNode>
"
);
return
sb.ToString();
}
2. UserXMLCreator.aspx 是一个空白的 Web 窗体
UserXMLCreator.aspx.cs 目的是生成用户节点,内容片段如下:
private
void
Page_Load(
object
sender, System.EventArgs e)
{
string
orgID
=
Request.QueryString[
"
oid
"
].ToString().Trim();
Response.ContentEncoding
=
System.Text.UTF8Encoding.UTF8;
if
(orgID.Length
>
0
)
{
Response.Write (CreateXml(orgID));
}
Response.End();
}
public
string
CreateXml(
string
orgID)
{
StringBuilder sb
=
new
StringBuilder();
//
sb.Append("<?xml version=\"1.0\" encoding=\"gb2312\"?>\r\n");
sb.Append(
"
<TREENODES>\r\n
"
);
DataTable dt
=
new
DataTable();
dt
=
DataProvider.Instance.GetUsersInOrganization(orgID).Tables[
0
];
sb.Append(CreateList(dt));
sb.Append(
"
</TREENODES>
"
);
return
sb.ToString();
}
protected
string
CreateList(DataTable dt)
{
StringBuilder sb
=
new
StringBuilder();
try
{
DataRow[] drs
=
dt.Select();
foreach
(DataRow dr
in
drs)
{
sb.Append(CreateElement(dr));
}
return
sb.ToString();
}
catch
{
return
""
;
}
}
protected
string
CreateElement(DataRow dr)
{
StringBuilder sb
=
new
StringBuilder();
string
id
=
dr[
"
id
"
].ToString();
//
set attribute NodeData to userid
sb.Append(
"
<TreeNode NodeData=\
""
);
sb.Append(id);
//
set attribute Text to zhname
sb.Append(
"
\
"
Text
=
\
""
);
sb.Append(dr[
"
zhname
"
].ToString());
sb.Append(
"
\
"
"
);
//
set other attributes
sb.Append(
"
Checkbox=\
"
true
\
"
Type=\
"
user\
"
Expanded=\
"
false
\
"
"
);
sb.Append(
"
>\r\n
"
);
sb.Append(
"
</TreeNode>
"
);
return
sb.ToString();
}
3. TreeCreator.aspx 负责产生整棵树,并为用户提供对树节点的操作界面
1)用于产生树的代码片段
在 aspx 页面头部声明使用 Microsoft.Web.UI.WebControls 控件集合:
<%
@ Register TagPrefix
=
"
iewc
"
Namespace
=
"
Microsoft.Web.UI.WebControls
"
Assembly
=
"
Microsoft.Web.UI.WebControls
"
%>
在 aspx 页面中声明使用微软的 TreeView 控件:
<
iewc:treeview
id
="TreeView1"
runat
="server"
ExpandedImageUrl
="images/folderopen.gif"
SystemImagesPath
="/webctrl_client/1_0/treeimages/"
ImageUrl
="images/folder.gif"
EnableViewState
="False"
></
iewc:treeview
>
用于初始化树的 JS 代码:
<
script language
=
"
javascript
"
>
function
InitTree()
{
TreeView1.treeNodeSrc
=
"
OrgXMLCreator.aspx?oid=0
"
; // 根节点,延迟异步加载其下属节点
TreeView1.databind();
}
</
script
>
用于立即初始化树的 HTML 代码:
<
body
onload
="javascript:InitTree();"
>
2)控制树节点 CHECKBOX 多选操作的通用 JS 代码
var
ids
=
""
;
var
uids
=
""
;
var
orgName
=
""
;
function
tree_oncheck(tree) // 鼠标选中时激发的事件
{
var
selectNode
=
tree.getTreeNode(tree.clickedNodeIndex)
CheckChildren(tree,selectNode.getChildren(),selectNode.getAttribute(
"
checked
"
));
CheckParent(tree,selectNode.getParent(),selectNode.getAttribute(
"
checked
"
));
orgName
=
""
;
ids
=
""
;
uids
=
""
;
GetSelectIDs(tree);
}
function
GetChildren(Node) // 获取某个节点的下级节点
{
var
NodeArray
=
new
Array();
NodeArray
=
Node.getChildren();
if
(NodeArray.length
==
0
)
{
return
;
}
for
(
var
i
=
0
;i
<
NodeArray.length;i
++
)
{
var
cNode
=
NodeArray[i];
if
(cNode.getAttribute(
"
Checked
"
))
{
orgName
+=
"
[
"
+
getFullPath(cNode)
+
cNode.getAttribute('Text')
+
"
]
"
;
if
(cNode.getAttribute(
"
Type
"
)
==
"
ou
"
)
{
if
(ids
!=
""
){
ids
+=
"
,
"
+
"
\'
"
+
cNode.getAttribute(
"
NodeData
"
)
+
"
\'
"
;
}
else
{
ids
+=
"
\'
"
+
cNode.getAttribute(
"
NodeData
"
)
+
"
\'
"
;
}
}
else
if
(cNode.getAttribute(
"
Type
"
)
==
"
user
"
)
{
if
(uids
!=
""
){
uids
+=
"
,
"
+
"
\'
"
+
cNode.getAttribute(
"
NodeData
"
)
+
"
\'
"
;
}
else
{
uids
+=
"
\'
"
+
cNode.getAttribute(
"
NodeData
"
)
+
"
\'
"
;
}
}
}
else
{
GetChildren(cNode);
}
}
}
function
GetSelectIDs(tree) // 获取整棵树有哪些节点被选中了
{
var
NodeArray
=
new
Array();
NodeArray
=
tree.getChildren();
for
(
var
i
=
0
;i
<
NodeArray.length;i
++
)
{
var
cNode
=
NodeArray[i];
if
(cNode.getAttribute(
"
Checked
"
))
{
orgName
+=
"
[
"
+
getFullPath(cNode)
+
cNode.getAttribute('Text')
+
"
]
"
;
if
(cNode.getAttribute(
"
Type
"
)
==
"
ou
"
)
{
if
(ids
!=
""
){
ids
+=
"
,
"
+
"
\'
"
+
cNode.getAttribute(
"
NodeData
"
)
+
"
\'
"
;
}
else
{
ids
+=
"
\'
"
+
cNode.getAttribute(
"
NodeData
"
)
+
"
\'
"
;
}
}
else
if
(cNode.getAttribute(
"
Type
"
)
==
"
user
"
)
{
if
(uids
!=
""
){
uids
+=
"
,
"
+
"
\'
"
+
cNode.getAttribute(
"
NodeData
"
)
+
"
\'
"
;
}
else
{
uids
+=
"
\'
"
+
cNode.getAttribute(
"
NodeData
"
)
+
"
\'
"
;
}
}
}
else
{
GetChildren(cNode);
}
}
document.getElementById(
"
hiddenOrgName
"
).innerText
=
orgName;
document.getElementById(
"
hiddenOrgID
"
).innerText
=
ids;
document.getElementById(
"
hiddenUsrID
"
).innerText
=
uids;
}
function
CheckChildren(tree,Nodes,TF) // 自动选中下属节点
{
var
dft
=
0
;
if
(parseInt(Nodes.length)
==
0
)
{
return
;
}
else
{
for
(
var
i
=
0
;i
<
parseInt(Nodes.length);i
++
)
{
Nodes[i].setAttribute(
"
Checked
"
,TF);
CheckChildren(tree,Nodes[i].getChildren(),TF);
}
}
}
function
CheckParent(tree,Node,TF) // 自动选中父级、爷爷级、太公级的节点
{
if
(Node
==
null
)
{
return
;
}
else
{
if
(TF)
{
}
else
{
Node.setAttribute(
"
Checked
"
,
false
);
CheckParent(tree,Node.getParent(),
false
);
}
}
}
function
tree_onclick(tree) // 点击节点文字激发的事件
{
//
alert(tree.getTreeNode(tree.clickedNodeIndex).getAttribute("Text"));
try
{
var
selectNode
=
tree.getTreeNode(tree.clickedNodeIndex)
//
alert(document.getElementById("lblNewOrgName").innerText);
if
(selectNode.getAttribute('NodeData')
==
null
)
{
//
alert("您不是该组织的管理员!移动到该组织");
}
else
{
document.getElementById(
"
hiddenOrgID
"
).innerText
+=
selectNode.getAttribute('NodeData')
+
'
|
';
var
txt
=
getFullPath(selectNode)
+
selectNode.getAttribute('Text');
document.getElementById(
"
lblNewOrgName
"
).innerHTML
+=
"
[
"
+
txt
+
"
]
"
;
}
if
(selectNode.getAttribute('Expanded'))
{
selectNode.setAttribute('Expanded','False');
}
else
{
selectNode.setAttribute('Expanded','True');
}
}
catch
(e)
{
throw
e;
}
}
function
getFullPath(node) // 取得节点的完整路径,获得路径中各级节点的文字并用“-”分隔开。
{
var
baseNode
=
node.getParent();
if
(baseNode
!=
null
)
{
var
txt
=
baseNode.getAttribute('Text');
//
alert(txt);
return
getFullPath(baseNode)
+
txt
+
"
--
"
;
}
return
""
;
}
代码完毕。