我有一个树视图,它有一些父节点和子节点。如果选择子节点,则应选择父节点。此功能正常工作,但如果父节点有多个子节点,并且我检查了多个子节点并取消选中,则取消选中一个子节点父节点。
如果选择了子节点,我已经完成了选择父节点的一些代码。
private bool updatingTreeView;
private void treSelector_AfterCheck(object sender, TreeViewEventArgs e)
{
if (updatingTreeView) return;
updatingTreeView = true;
SelectParents(e.Node, e.Node.Checked);
updatingTreeView = false;
}
private void SelectParents(TreeNode node, Boolean isChecked)
{
if (node.Parent != null)
{
node.Parent.Checked = isChecked;
SelectParents(node.Parent, isChecked);
}
}
如果检查了该父节点的任何单个子节点,我不希望未经检查的父节点。
答案 0 :(得分:7)
private void SelectParents(TreeNode node, Boolean isChecked)
{
var parent = node.Parent;
if (parent == null)
return;
if (isChecked)
{
parent.Checked = true; // we should always check parent
SelectParents(parent, true);
}
else
{
if (parent.Nodes.Cast<TreeNode>().Any(n => n.Checked))
return; // do not uncheck parent if there other checked nodes
SelectParents(parent, false); // otherwise uncheck parent
}
}
相同,重构
private void SelectParents(TreeNode node, Boolean isChecked)
{
var parent = node.Parent;
if (parent == null)
return;
if (!isChecked && HasCheckedNode(parent))
return;
parent.Checked = isChecked;
SelectParents(parent, isChecked);
}
private bool HasCheckedNode(TreeNode node)
{
return node.Nodes.Cast<TreeNode>().Any(n => n.Checked);
}
答案 1 :(得分:1)
如果您取消选中某个项目,将会引发事后检查事件,您将调用SelectParents来传播取消选中。
如果只在选中时才需要行为,只需在e.Node.Checked为true(或选中)时运行SelectParents。 但是,如果您取消选中之前检查过的唯一子项目,则不会取消选中父项(因此您可能检查了父项而未检查任何子项)。
答案 2 :(得分:1)
这是一个完整的例程,如果您检查父级,则选择子级 如果你设置了任何孩子,请检查父母
void tw_AfterCheck(对象发送者,TreeViewEventArgs e){
if (treeView.Enabled) {
treeView.AfterCheck -= tw_AfterCheck;
TreeNode node = e.Node;
if (node.Nodes != null)
node.Nodes.Cast<TreeNode>().ToList().ForEach(v => v.Checked = node.Checked);
node = e.Node.Parent;
while (node != null) {
bool set = e.Node.Checked
? node.Nodes.Cast<TreeNode>()
.Any(v => v.Checked == e.Node.Checked)
: node.Nodes.Cast<TreeNode>()
.All(v => v.Checked == e.Node.Checked);
if (set) {
node.Checked = e.Node.Checked;
node = node.Parent;
}
else
node = null;
}
treeView.AfterCheck += tw_AfterCheck;
}
}
答案 3 :(得分:0)
当您去验证每个父母时,您需要验证该父母的所有孩子,因为您不知道取消选中该节点是否是最后一个:
private void VerifyChecked(TreeNode node)
{
var current = node;
while (current != null)
{
current.Checked = current.Nodes.Cast<TreeNode>()
.Any(child => child.Checked);
current = current.Parent;
}
}
请注意,我重构了它以验证传入的节点,而不是其父节点,因此您需要修改调用它以传递e.Node.Parent
。
答案 4 :(得分:0)
在创建类似功能时,我引用了此文章和其他文章,并认为我会分享,以防它对其他人有帮助。
所需功能:
检查父节点将检查所有子节点。
取消选中子节点将取消选中所有父节点,以表示未选中所有子节点。
/// <summary>
/// Propagates checked state downwards to all children and upwards unchecked to parents.
/// Parents are unchecked to visually signify that not all children are checked.
/// </summary>
/// <param name="currentNode"></param>
/// <param name="nodeChecked"></param>
private void CheckedUncheckedPropagateTreeNode(TreeNode currentNode, bool nodeChecked)
{
// Check if current node has children.
foreach (TreeNode node in currentNode.Nodes)
{
// Update checked status of this child node.
node.Checked = nodeChecked;
// Recursively call method to handle all children of this child node.
CheckedUncheckedPropagateTreeNode(node, nodeChecked);
}
// If the node was unchecked uncheck all parent nodes.
if (!nodeChecked)
{
// Set parent node initial if available.
TreeNode parentNode = currentNode.Parent;
// Traverse tree nodes upwards to uncheck all parents.
while (parentNode != null)
{
// Set parent checked value.
parentNode.Checked = nodeChecked;
// Set new parent node to continue while loop to the top of the tree view.
parentNode = parentNode.Parent;
}
}
}