我是新手使用树视图,我希望能够确保树视图只能检查一个子节点,如果有人试图检查多一个,它会停止检查事件并取消选择所有父节点和子节点。我该怎么做呢?到目前为止,这是我所拥有的,但它表现得很古怪。有什么建议吗?
更新:为了澄清一些事情,这是一个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();
}
}
}
}
答案 0 :(得分:1)
仅仅发表评论太长了。
我假设您正在描述标准的Windows窗体TreeView:正确吗?
当你在问题中说:
如果有人试图检查更多 一个它停止检查事件和 取消选择所有父节点和子节点。
对我而言,这意味着您有一个能够进行多项选择的树视图,并且标准的Windows窗体TreeView 不能够做到这一点。你可以“破解它”,因此它可以进行多项选择:例如:CodeProject : "Multiselect Treeview Implementation",但这样做并非易事。
所以我假设你的意思是“取消选中”父节点和子节点:但后来:这很令人困惑,因为你的问题似乎清楚地询问你如何在一个方面只检查一个子TreeNode时间:这对我来说意味着你永远不会“取消选中”任何其他子节点。
阅读代码时,很明显您正在计划检查一个父节点的可能性,但是您没有明确排除可以检查多个“无父”(根)节点的情况。
因此,建议更清楚地重新陈述您的问题以澄清:
可以检查多个无父(根)节点吗?
一次只能检查一个无父(根)节点吗?
对于每个选中的无父(根)节点,可以同时检查一个且只有一个子节点吗?
如果子节点“深度嵌套”:这对您有什么影响吗?
注意:由于本机WinForms TreeView控件的很大限制,我们很多人已经购买了第3个。派对TreeView控件:
我购买了Integral UI TreeView from Lidor Systems,并对此很满意。 Lidor TreeView的内置属性是'CheckedNodes集合,其中包含所有当前已检查的节点,您可以选择三种选择模式,包括一个“MultiExtended”,允许您进行包含子节点和父节点的非常复杂的选择。任何秩序,在任何“嵌套”级别:
当然,您可以随时使用包含所有选定节点的“SelectedNodes”集合。
使用Lidor TreeView,您可以随时(在设计时或运行时)隐藏任何一个节点的CheckBox,CheckBox支持三种状态:'不确定以及'已选中'和未选中。< / p>
我假设其他第3名。派对TreeView控件也提供了类似的功能,但是当我两年前回顾并尝试了大多数主要版本的“试用版”时:对我而言,Lidor TreeView提供了最大的价值并且并不昂贵。在丰富“样式化”TreeNodes的能力方面,我没有看到任何与“WinForms Universe”中Lidor TreeView的能力相近的东西。披露:我不为Lidor工作,与他们没有业务关系:我只是一个很乐意推荐的客户。
答案 1 :(得分:1)
你的if(checkedNodeCount&gt; 2)...应该在foreach循环之外。
在for循环中,每次都会运行。我假设你的意思是“表演古怪”
也许你应该提供一些关于不正确行为的更多细节。
答案 2 :(得分:1)
希望这有效:
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;
}
}
}
答案 3 :(得分:0)
1年前被问过,但there是提示,如何在Treeview中只选择一个节点