【问题标题】:Aftercheck and AfterSelect events in Treeview in Windows FormsWindows 窗体中 Treeview 中的 Aftercheck 和 AfterSelect 事件
【发布时间】:2020-02-19 16:59:15
【问题描述】:

我正在设置一个新表单,并且我在 TreeViewNodes 检查和取消检查子项时遇到了一些问题。在这个short clip 中更容易看到问题

通常它可以正常工作,但有时会卡住(我认为与选择有冲突,但我不确定)并且方法没有正确应用。

我有这个方法来检查和取消选中孩子:

private void Treeview_AfterCheck(object sender, TreeViewEventArgs e)
{
    if (e.Action != TreeViewAction.Unknown)
        if (e.Node.Checked)
        {
            CheckAll(e.Node.Nodes);
        }
        if (e.Node.Checked == false)
        {
            Uncheckall(e.Node.Nodes);
        }
}

public void Uncheckall(TreeNodeCollection nodes)
{
    foreach (TreeNode node in nodes)
    {
        node.Checked = false;
        foreach (TreeNode node1 in node.Nodes)
        {
            node1.Checked = false;
            foreach (TreeNode node2 in node1.Nodes)
            {
                node2.Checked = false;
            }
        }
    }
}


public void CheckAll(TreeNodeCollection nodes)
{
    foreach (TreeNode node in nodes)
    {
        node.Checked = true;
        foreach (TreeNode node1 in node.Nodes)
        {
            node1.Checked = true;
            foreach (TreeNode node2 in node1.Nodes)
            {
                node2.Checked = true;
            }
        }
    }
}

我已经尝试将选择设为空:

private void TreeView_Select(object sender, TreeViewEventArgs e)
{
    TreeView.SelectedNode = null;
}

但问题仍然存在。有任何想法吗?谢谢

【问题讨论】:

标签: c# .net winforms treeview


【解决方案1】:

我在评论中提到的question 的答案向我们展示了有关如何迭代TreeView 节点的不同方式。为此,您需要一个递归函数,它是一个调用自身的函数

现在,回到您的代码。您不需要创建两个函数来检查和取消选中节点,也不需要为每个节点、子节点和子节点的子节点使用foreach...等。请尝试以下方法:

private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
{
    if (e.Action == TreeViewAction.Unknown) { return; }

    foreach (TreeNode tn in GetNodes(e.Node))
        tn.Checked = e.Node.Checked;
}

private static IEnumerable<TreeNode> GetNodes(TreeNode parentNode)
{
    foreach (TreeNode tn in parentNode.Nodes)
    {
        yield return tn;

        foreach (TreeNode child in GetNodes(tn))
        {
            yield return child;
        }
    }
}

这样,您可以使用此迭代器对节点执行其他操作,而不仅仅是选中/取消选中它们。

编辑

您可以在 7、10、15 秒内看到这种奇怪的行为。

我现在明白你的意思了。

当您在节点上单击鼠标太快时会发生这种行为,因此您实际上是在执行鼠标单击、鼠标双击序列。默认情况下,树视图控件不会通过鼠标双击来切换节点的检查状态,除非您告诉它这样做。如何?已由PhilPthis 问题中回答。

  • 创建一个继承树视图控件的新类并覆盖 WndProc 事件,如下所示:
class TreeViewEx : TreeView
{

    public TreeViewEx()
    { }

    #region This extra to reduce the flickering

    private const int TVM_SETEXTENDEDSTYLE = 0x1100 + 44;
    private const int TVM_GETEXTENDEDSTYLE = 0x1100 + 45;
    private const int TVS_EX_DOUBLEBUFFER = 0x4;

    [DllImport("user32.dll")]
    private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);

    protected override void OnHandleCreated(EventArgs e)
    {
        SendMessage(Handle, TVM_SETEXTENDEDSTYLE, (IntPtr)TVS_EX_DOUBLEBUFFER, (IntPtr)TVS_EX_DOUBLEBUFFER);
        base.OnHandleCreated(e);
    }

    #endregion

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == 0x203 && CheckBoxes)
        {
            int x = m.LParam.ToInt32() & 0xffff;
            int y = (m.LParam.ToInt32() >> 16) & 0xffff;
            TreeViewHitTestInfo hitTestInfo = HitTest(x, y);

            if (hitTestInfo.Node != null && hitTestInfo.Location == TreeViewHitTestLocations.StateImage)
            {
                OnBeforeCheck(new TreeViewCancelEventArgs(hitTestInfo.Node, false, TreeViewAction.ByMouse));
                hitTestInfo.Node.Checked = !hitTestInfo.Node.Checked;
                OnAfterCheck(new TreeViewEventArgs(hitTestInfo.Node, TreeViewAction.ByMouse));
                m.Result = IntPtr.Zero;
                return;
            }
        }

        base.WndProc(ref m);
    }
}
  • 在包含您的TreeView 的表单设计器中,将TreeView 的类型更改为我们刚刚创建的扩展类型。

  • 使用相同的代码来切换检查状态。

  • 重建您的项目。

就是这样。

这是一个快速演示。我疯狂地点击鼠标并双击。但是,它可以正常工作。希望。


相关


CheckBox not work properly when clicked on quickly multiple times


【讨论】:

  • 非常感谢你的回答。我想我应该更好地解释自己。我现在要尝试澄清我的问题。 1-首先,您显示的代码显然比我的原始代码更好更干净(包含所有不必要的 foreach 循环等)。事实上,我已经用你提出的那个代码改变了我的代码。 2-Second,关键是,即使我的代码很糟糕,那也不是我的问题,我的问题仍然存在。很难清楚地解释发生了什么,这就是我上传视频的原因。您可以在 7、10、15 秒内看到这种奇怪的行为。
  • 哇,虽然我不明白那个类里面的代码。它就像一个魅力! (稍后我会给自己时间来处理代码)。非常感谢。这个论坛是金!谢谢!
猜你喜欢
  • 2023-04-10
  • 1970-01-01
  • 2012-03-27
  • 1970-01-01
  • 1970-01-01
  • 2018-12-10
  • 2011-03-05
  • 1970-01-01
  • 2014-09-27
相关资源
最近更新 更多