【发布时间】:2011-12-01 03:51:47
【问题描述】:
我有一个树视图,并且复选框设置为 true。我想要的是在整个树视图中只选择一个复选框。我该怎么做?
仅供参考:树视图的深度为三层。
【问题讨论】:
-
我在这里找到了解决方案codeproject.com/Tips/242364/Select-only-one-node-in-Treeview 并且效果很好
我有一个树视图,并且复选框设置为 true。我想要的是在整个树视图中只选择一个复选框。我该怎么做?
仅供参考:树视图的深度为三层。
【问题讨论】:
最简单的方法是为树视图的 AfterCheck 事件设置一个偶数处理程序。在这个处理程序中,您可以取消选中除刚刚选中的节点之外的所有节点:
void node_AfterCheck(object sender, TreeViewEventArgs e) {
// only do it if the node became checked:
if (e.Node.Checked) {
// for all the nodes in the tree...
foreach (TreeNode cur_node in e.Node.TreeView.Nodes) {
// ... which are not the freshly checked one...
if (cur_node != e.Node) {
// ... uncheck them
cur_node.Checked = false;
}
}
}
}
应该可以(没试过)
【讨论】:
这是一篇旧帖子,尽管提供的解决方案都不适用于我的情况。
所以我做了如下,
private TreeNode uncheck_treeview(TreeView treeView, TreeNode treeNode, TreeViewEventHandler e)
{
treeView.AfterCheck -= e;
foreach (TreeNode node in treeView.Nodes)
{
uncheck_treenode_tree(node);
}
if (treeNode != null)
{
treeNode.Checked = true;
}
treeView.AfterCheck += e;
return treeNode;
}
和
private void uncheck_treenode(TreeNode treeNode)
{
treeNode.Checked = false;
foreach (TreeNode node in treeNode.Nodes)
{
uncheck_treenode_tree(node);
}
}
和
private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
{
var checkedNode = uncheck_treeview_tree((TreeView) sender, e.Node, treeView1_AfterCheck);
// further processing ...
}
请注意,此方法可防止 StackOverflowException !
希望对他人有用
【讨论】:
我试过了,确实有效
bool manualcheck = false;
protected override void OnAfterCheck(TreeViewEventArgs e)
{
if (manualcheck) return;
if (e.Node.Checked)
{
if (Nodes.Count>0) UnCheckAll(Nodes[0]);
manualcheck = true;
e.Node.Checked = true;
manualcheck = false;
}
}
void UnCheckAll(TreeNode node)
{
if (node != null)
{
node.Checked = false;
foreach (TreeNode item in node.Nodes)
{
manualcheck = true;
item.Checked = false;
if (item.Nodes.Count > 0) UnCheckAll(item.Nodes[0]);
}
if (node.NextNode != null)
UnCheckAll(node.NextNode);
}
manualcheck = false;
}
【讨论】:
我也遇到了同样的问题,但是循环遍历所有节点听起来对性能很昂贵。
这是我的解决方案,没有循环遍历所有节点,而是使用类属性:
public partial class GuiDefault // not my whole class, just an example
{
TreeNode checkedNode = null;
private void Tree_AfterCheck(object sender, TreeViewEventArgs e)
{
TreeNode checkedNodeVar = e.Node;
if (checkedNodeVar.Checked)
{
if (checkedNode != null)
{
checkedNode.Checked = false; // set "checked" property of the last checked box to false
}
checkedNode = checkedNodeVar; // set the class property "checkedNode" to the currently checked Node
}
else
{
checkedNode = null; // if current checked box gets unchecked again, also reset the class property "checkedNode"
}
}
}
我发现此解决方案的唯一问题是,如果用户将相同的复选框切换为快速,则该函数不会被正确调用,并且它不会在单击后单击 1 次“选中”或“取消选中”该框然后两次。
也许其他人可以添加一个修复程序,以在运行时快速单击相同的复选框。
【讨论】:
// Upon node checked, uncheck all other nodes
private void tvAccountHierarchy_AfterCheck(object sender, TreeViewEventArgs e)
{
// only do it if the node became checked:
if (e.Node.Checked)
{
Uncheck_Treenodes(e.Node.TreeView.Nodes, e.Node);
}
}
//Recursively iterate through all child nodes and uncheck all except the checkedNode
private void Uncheck_Treenodes(TreeNodeCollection treeNodes, TreeNode checkedNode)
{
// iterate through child nodes & uncheck
foreach (TreeNode cur_node in treeNodes)
{
if (cur_node != checkedNode)
{
// ... uncheck them
cur_node.Checked = false;
}
Uncheck_Treenodes(cur_node.Nodes, checkedNode);
}
}
【讨论】:
我使用here找到的解决方案。
页面中的javascript
function client_OnTreeNodeChecked(event)
{
var treeNode = event.srcElement || event.target ;
if (treeNode.tagName == "INPUT" && treeNode.type == "checkbox")
{
if(treeNode.checked)
{
uncheckOthers(treeNode.id);
}
}
}
function uncheckOthers(id)
{
var elements = document.getElementsByTagName('input');
// loop through all input elements in form
for(var i = 0; i < elements.length; i++)
{
if(elements.item(i).type == "checkbox")
{
if(elements.item(i).id!=id)
{
elements.item(i).checked=false;
}
}
}
}
以及将 client_OnTreeNodeChecked 函数添加到您的树视图 onclick 事件的代码
private void Page_PreRender(object sender, EventArgs e)
{
TreeView1.Attributes.Add("OnClick", "client_OnTreeNodeChecked(event)");
}
注意:如果 TreeView 在 UpdatePanel 中,请阅读我的帖子 How to make javascript work along with Ajax UpdatePanel
【讨论】:
This solution 我无耻地窃取了它,让你可以一次性遍历所有级别的所有节点。
这使得确保只选择一个节点变得容易:
foreach (var node in resultsTree.GetAllNodes())
{
if (node != e.Node) node.Checked = false;
}
【讨论】:
<script type="text/javascript">
function MakeRadio() {
var tv = document.getElementById("<%= position_TreeView.ClientID %>");
var chkArray = tv.getElementsByTagName("input");
for (i = 0; i <= chkArray.length - 1; i++) {
if (chkArray[i].type == 'checkbox') {
chkArray[i].type = 'radio';
chkArray[i].name = 'YaMahdi';
}
}
}
window.onload = MakeRadio;
</script>
<script type="text/javascript">
function OnTreeClick(evt) {
var src = window.event != window.undefined ? window.event.srcElement : evt.target;
var isChkBoxClick = (src.tagName.toLowerCase() == "input" && src.type == "radio");
if (isChkBoxClick) {
SelectOne(src.id);
}
}
function SelectOne(objId) {
var tv = document.getElementById("<%= position_TreeView.ClientID %>");
var chkArray = tv.getElementsByTagName("input");
for (i = 0; i <= chkArray.length - 1; i++) {
if (chkArray[i].type == 'radio') {
if (chkArray[i].id != objId) {
chkArray[i].checked = false;
}
}
}
}
</script>
【讨论】: