【问题标题】:Check or uncheck all TreeViewItem children选中或取消选中所有 TreeViewItem 子项
【发布时间】:2010-07-20 12:49:13
【问题描述】:

我的项目是 WinForms,C#。

我有一个带有 TreeView 的表单,其中 CheckBoxes 设置为 true。有几个根节点,每个都有多个子节点。

我希望所有子节点都具有与其父节点相同的选中/未选中状态。我编写了以下事件处理程序:

private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
{
  // return in case the event is induced by the code below
  if (e.Action == TreeViewAction.Unknown)
  {
    return;
  }
  System.Diagnostics.Debug.WriteLine(string.Format("Checked - {0}", e.Node.Checked));
  foreach (TreeNode subNode in e.Node.Nodes)
  {
    subNode.Checked = e.Node.Checked;
  }
}

但是,当快速单击父级时,这会很奇怪。我可以通过快速检查和取消选中父节点来轻松重现这一点,以便在父节点已经取消选中时所有子节点都被选中。

如何更正确地做到这一点?

【问题讨论】:

  • 快速点击好像没有调用这个事件。我添加了 System.Diagnostics.Debug.WriteLine(string.Format("Checked - {0}", e.Node.Checked));到第一行,第二次(取消选中)单击时看不到“已选中 - 错误”。
  • 如果我覆盖了双击行为,我只能重现此行为。否则,快速单击只会扩展/收缩您正在单击的节点。
  • 中士,快速点击复选框,而不是项目文本。它不应展开或折叠。

标签: .net winforms treeview


【解决方案1】:

这是原生 TreeView 控件的 Vista 版本引入的错误。它通过自动切换复选框来响应双击。但没有引发 BeforeCheck 和 AfterCheck 事件。 Windows 窗体 TreeView 类包装器未更新以处理此问题。

修复很简单,你需要防止原生控件看到双击。向您的项目添加一个新类并粘贴如下所示的代码。编译。将新控件从工具箱顶部拖放到表单上,替换现有的树形视图。

using System;
using System.Windows.Forms;

public class MyTreeView : TreeView {
  protected override void WndProc(ref Message m) {
    // Suppress WM_LBUTTONDBLCLK
    if (m.Msg == 0x203) { m.Result = IntPtr.Zero; }
    else base.WndProc(ref m);
  }
}

【讨论】:

  • 谢谢,汉斯!这完美地工作。但是,覆盖双击并手动发送 AfterCheck 事件是否有意义?你觉得怎么样?
  • 那么您的程序将无法在 XP 上正常运行。这是可能的,但您必须在 base.WndProc 调用之后读取项目检查状态。 P/Invoke 很棘手。
【解决方案2】:

我们添加了一个计时器,可在您单击时启动/重置。如果计时器在 500 毫秒后触发,则执行实际的更新代码。

这将解决快速点击的问题。

【讨论】:

  • 谢谢 - 会尝试。然而,这让我惊讶的是,控件从未收到第二个事件!这似乎是框架错误。
【解决方案3】:

当您快速单击时,会触发双击事件而不是单击。单击行为是更改检查状态的原因。如果您已经做了一些事情来覆盖正常的双击行为,请确保在子节点上考虑到这一点。

【讨论】:

  • 不,我点击的速度很慢,无法接收到双击事件。我覆盖此事件以确保。
猜你喜欢
  • 2013-01-19
  • 2018-10-14
  • 2011-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-11
  • 1970-01-01
  • 2012-11-21
相关资源
最近更新 更多