检查TreeView中已检查节点的数量

我是新手使用树视图,我希望能够确保树视图只能检查一个子节点,如果有人试图检查多一个,它会停止检查事件并取消选择所有父节点和子节点。 我该怎么做呢? 到目前为止,这是我所拥有的,但它表现得很古怪。 有什么建议?

更新:为了澄清一些事情,这是一个win form treeview,父节点是一个类别,每个类别可以包含多个项目。 我只希望用户能够一次从类别中选择一个类别和一个项目。

private void tvRecipes_BeforeCheck(object sender, TreeViewCancelEventArgs e) { int checkedNodeCount = 0; if (e.Node.Parent != null && !e.Node.Parent.Checked) e.Cancel = true; else { foreach (TreeNode node in tvRecipes.Nodes) { if (node.Checked) ++checkedNodeCount; if (checkedNodeCount > 2) { MessageBox.Show("Only one recipe can be selected at a time, please deselect the current recipe and try again.", "Too Many Recipes Selected", MessageBoxButtons.OK, MessageBoxIcon.Error); e.Cancel = true; } } } 

经过一番捣乱,我想出了我追求的解决方案。 我在下面发布了它:

 private bool CheckNumOfSelectedChildern(TreeViewEventArgs e) { bool Valid = true; int selectedChildern = 0; foreach (TreeNode node in tvRecipes.Nodes) { if (node.Checked) { foreach (TreeNode child in node.Nodes) { if (child.Checked) ++selectedChildern; } } } if (selectedChildern > 1) { MessageBox.Show("Only one recipe per category can be selected at a time, please deselect the current recipe and try again.", "Too Many Recipes Selected", MessageBoxButtons.OK, MessageBoxIcon.Error); e.Node.Checked = false; e.Node.Parent.Checked = false; Valid = false; } return Valid; } private bool CheckNumOfSelectedParents(TreeViewEventArgs e) { bool Valid = true; int selectedParent = 0; foreach (TreeNode root in tvRecipes.Nodes) { if (root.Checked) ++selectedParent; } if (selectedParent > 1) { MessageBox.Show("Only one recipe category can be selected at a time, please deselect the current recipe and try again.", "Too Many Recipes Selected", MessageBoxButtons.OK, MessageBoxIcon.Error); e.Node.Checked = false; Valid = false; } return Valid; } private void tvRecipes_BeforeCheck(object sender, TreeViewCancelEventArgs e) { if (e.Node.Parent != null && !e.Node.Parent.Checked) e.Cancel = true; else if (e.Node.Checked) { foreach (TreeNode child in e.Node.Nodes) { if (child.Checked) e.Cancel = true; } } } private void tvRecipes_AfterCheck(object sender, TreeViewEventArgs e) { if (CheckNumOfSelectedParents(e)) { if (e.Node.Parent != null && e.Node.Parent.Checked) { if (e.Node.Checked) { if (CheckNumOfSelectedChildern(e)) { RecipeDs = RetrieveRecipe.FillRecipeDs(e.Node.Text); DataBindControls(); } } else { RemoveLabelsFromLayout(); RemoveDataBindings(); RecipeDs.Clear(); this.Refresh(); } } } } 

你的if(checkedNodeCount> 2)……应该在foreach循环之外。

在for循环中,它每次都会运行。 我假设你的意思是“表演古怪”

也许你应该提供一些关于错误行为的更多细节。

这对于评论来说太长了。

我假设您正在描述标准的Windows窗体TreeView:对吗?

当你在问题中说:

如果有人试图检查多一个它停止检查事件并取消选择所有父节点和子节点。

对我而言,这意味着您有一个能够进行多项选择的树视图,并且标准的Windows窗体TreeView 具备此function。 您可以“破解它”以便进行多选:例如: CodeProject:“Multiselect Treeview Implementation” ,但这样做并非易事。

所以我假设你的意思是“取消选中”父节点和子节点 :但那时:这很令人困惑,因为你的问题似乎清楚地询问你一次只能检查一个子TreeNode:这对我来说意味着它永远不会是你必须“取消选中”任何其他子节点的情况。

阅读代码时,很明显您正在计划检查一个父节点的可能性,但是您没有明确排除可以检查多个“无父”(根)节点的情况。

因此,建议更清楚地重新陈述您的问题以澄清:

  1. 可以检查多个无父(根)节点?

  2. 一次只能检查一个无父(根)节点?

  3. 对于每个选中的无父(根)节点,可以一次检查一个且只有一个子节点吗?

  4. 如果子节点“深度嵌套”:这对你有什么影响吗?

注意:由于本机WinForms TreeView控件的巨大限制,我们很多人已经购买了第三个。 派对TreeView控件:

我从Lidor Systems购买了Integral UI TreeView,并对它很满意。 Lidor TreeView的内置属性是’CheckedNodes集合,其中包含所有当前已检查的节点,您可以选择三种选择模式,包括一个“MultiExtended”,允许您进行包含子节点和父节点的非常复杂的选择。任何订单,在任何“嵌套”级别:

当然,您可以随时使用包含所有选定节点的“SelectedNodes”集合。

使用Lidor TreeView,您可以随时(在设计时或运行时)隐藏任何一个节点的CheckBox,CheckBox支持三种状态:’不确定以及’已选中和’未选中。

我假设其他第三。 派对TreeView控件也提供了类似的function,但是当我两年前审查并尝试了大多数主要版本的“试用版”时:对我而言,Lidor TreeView提供了最大的价值并且并不昂贵。 在丰富“样式化”TreeNodes的能力方面,我没有看到任何与“WinForms Universe”中Lidor TreeView的能力相近的东西。 披露:我不为Lidor工作,与他们没有业务关系:我只是一个很乐意推荐的客户。

希望这有效:

 private int _callCountUp; private int _callCountDn; private void tvwPermissions_AfterCheck(object sender, System.Windows.Forms.TreeViewEventArgs e) { bool anyChecked = false; if (_callCountDn == 0 && e.Node.Parent != null) { anyChecked = false; foreach (TreeNode childNode in e.Node.Parent.Nodes) { if (childNode.Checked) { anyChecked = true; break; } } _callCountUp += 1; if (anyChecked) e.Node.Parent.Checked = true; _callCountUp -= 1; } if (_callCountUp == 0) { foreach (TreeNode childNode in e.Node.Nodes) { _callCountDn += 1; childNode.Checked = e.Node.Checked; _callCountDn -= 1; } } } 

它在1年前被问过,但有一个提示,如何在Treeview中只选择一个节点