【问题标题】:How to make Treeview check only one option如何让 Treeview 只检查一个选项
【发布时间】:2011-12-01 03:51:47
【问题描述】:

我有一个树视图,并且复选框设置为 true。我想要的是在整个树视图中只选择一个复选框。我该怎么做?

仅供参考:树视图的深度为三层。

【问题讨论】:

标签: c# winforms treeview


【解决方案1】:

最简单的方法是为树视图的 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;
            }
        }
    }
}

应该可以(没试过)

【讨论】:

  • 经过我的尝试,它只适用于一级节点。它的子节点没有被取消选中。 cmiiw
  • 不只是迭代 TreeView 中的节点,您需要递归迭代所有节点,并取消选中它们....请注意,如果您的 TreeView 有 A很多节点....
【解决方案2】:

这是一篇旧帖子,尽管提供的解决方案都不适用于我的情况。

所以我做了如下,

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

希望对他人有用

【讨论】:

    【解决方案3】:

    我试过了,确实有效

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

    【讨论】:

      【解决方案4】:

      我也遇到了同样的问题,但是循环遍历所有节点听起来对性能很昂贵。

      这是我的解决方案,没有循环遍历所有节点,而是使用类属性:

      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 次“选中”或“取消选中”该框然后两次。

      也许其他人可以添加一个修复程序,以在运行时快速单击相同的复选框。

      【讨论】:

        【解决方案5】:
        // 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);
                }
            }
        

        【讨论】:

        • 请添加更多详细信息以扩展您的答案,例如工作代码或文档引用。
        【解决方案6】:

        我使用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

        【讨论】:

          【解决方案7】:

          This solution 我无耻地窃取了它,让你可以一次性遍历所有级别的所有节点。

          这使得确保只选择一个节点变得容易:

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

          【讨论】:

          • 这是一个 winform 问题,您的答案是针对 ASP.Net 控件。
          【解决方案8】:

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

          【讨论】:

          • winform 需要回答。
          猜你喜欢
          • 2015-07-20
          • 1970-01-01
          • 1970-01-01
          • 2015-12-27
          • 2010-11-26
          • 2011-07-22
          • 1970-01-01
          • 1970-01-01
          • 2012-04-30
          相关资源
          最近更新 更多