简体   繁体   English

如何使Treeview仅检查一个选项

[英]How to make Treeview check only one option

I have a treeview and Checkbox is set true. 我有一个Treeview,并且Checkbox设置为true。 What I want is that only one checkbox is selected in the whole treeview. 我想要的是在整个树视图中仅选中一个复选框。 How can I do that? 我怎样才能做到这一点?

FYI: the treeview is in three level depth. 仅供参考:树形视图的深度为三层。

The simplest way to do that is to set an even handler to your tree view's AfterCheck event. 最简单的方法是为树视图的AfterCheck事件设置一个偶数处理程序。 In this handler you can uncheck all the nodes but the one which just became checked: 在此处理程序中,您可以取消选中除已选中的节点以外的所有节点:

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;
            }
        }
    }
}

Should work (didn't try) 应该工作(没有尝试)

It is an old post, though none of provided solutions is working in my case. 尽管我提供的解决方案都无法正常工作,但这是一个古老的帖子。

So I did as follows, 所以我做了如下

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;
}

and

private void uncheck_treenode(TreeNode treeNode)
{
    treeNode.Checked = false;
    foreach (TreeNode node in treeNode.Nodes)
    {
        uncheck_treenode_tree(node);
    }
}

and

private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
{
    var checkedNode = uncheck_treeview_tree((TreeView) sender, e.Node, treeView1_AfterCheck);
    // further processing ...
}

note that this method prevents StackOverflowException ! 请注意,此方法可防止StackOverflowException

hope useful to others 希望对他人有用

I tried it certainly works 我尝试过它肯定有效

       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;
            }

I had the same issue, but looping trough all Nodes sounds expensive for performance. 我遇到了同样的问题,但是循环遍历所有节点听起来对性能来说是昂贵的。

Here is my solution without looping trough all Nodes, but using a class property: 这是我的解决方案,不循环所有节点,而是使用类属性:

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"
                    }
    }

}

The only issue i found with this solution is that if the user toggle the same checkbox to fast, the function doesn't get called correctly and it doesnt "check" or "uncheck" the box with 1 click, just after clicking it twice then. 我在此解决方案中发现的唯一问题是,如果用户将同一复选框快速切换,则该函数将无法正确调用,并且单击两次后便不会“单击”或“取消选中”该框。 。

Maybe someone else can add a fix for clicking the same checkbox to fast at runtime. 也许其他人可以添加一个修复程序,以单击同一复选框以快速运行。

This solution which I shamelessly stole allows you to iterate over all nodes at all levels in one go. 我毫不留情地偷走了这个解决方案 ,使您可以一次遍历所有级别的所有节点。

This makes ensuring only one node is selected easy: 这使得确保仅选择一个节点变得容易:

    foreach (var node in resultsTree.GetAllNodes())
    {
        if (node != e.Node) node.Checked = false;
    }

I use the solution found here . 我使用这里找到的解决方案。

A javascript in the page 页面中的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;
     }
    }
   }
  }

And code behind to add client_OnTreeNodeChecked function to your treeviews onclick event 后面的代码将client_OnTreeNodeChecked函数添加到treeviews onclick事件

private void Page_PreRender(object sender, EventArgs e)
 {
  TreeView1.Attributes.Add("OnClick", "client_OnTreeNodeChecked(event)");
 }

NOTE: read my post How to make javascript work along with Ajax UpdatePanel if TreeView is inside an UpdatePanel 注意:如果TreeView位于UpdatePanel中,请阅读我的文章如何使javascript与Ajax UpdatePanel一起使用

在此处输入图片说明

        <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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM