Windows窗体中Treeview中的Aftercheck和AfterSelect事件 [英] Aftercheck and AfterSelect events in Treeview in Windows Forms

查看:416
本文介绍了Windows窗体中Treeview中的Aftercheck和AfterSelect事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在建立一个新的Form,并且我正在使用TreeViewNodes检查并取消子项的发行问题.在此


相关


快速单击多次后,CheckBox不能正常工作


Im setting up a new Form and Im having some issuis with the TreeViewNodes checking and uncheking the childs. Its easier to see the problem in this short clip

Normally it works properly but sometimes it gets stuck (I think there is a conflict with selection but Im not sure) and the methods arent applied properly.

I have this methods to check and uncheck the childs:

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;
            }
        }
    }
}

And I have tried to make the selection null:

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

But the problem remains. Any ideas? Thanks

解决方案

The answers of the question that I mentioned in my comment shows us different ways regarding how to iterate through TreeView nodes. To do that, you need a Recursive Function which is a function that calls itself.

Now, back to your code. You don't need to create two functions to check and uncheck the nodes, nor using foreach for each node, child node, and child node of a child node...etc. Please try the following:

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;
        }
    }
}

This way, you can use this iterator to do other things to your nodes not only to check/uncheck them.

Edit

You can see this strange behaviour in the seconds 7, 10, 15.

I got your point now.

That behavior occurs when you mouse click too fast on a node so you are actually doing mouse click, mouse double click sequence. The tree view control by default does not toggle the check state of the nodes through the mouse double click unless you tell it to do so. How? Already answered by PhilP in this question.

  • Create a new class that inherits the tree view control and override the WndProc event as follow:

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);
    }
}

  • In the designer of the form which contains your TreeView, change the type of the TreeView to the extended one that we just created.

  • Use the same code to toggle the check state.

  • Rebuild your project.

That's it all.

Here is a quick demo. I'm mouse clicking and double clicking like crazy. However, it works as it should. Hopefully.


Related


CheckBox not work properly when clicked on quickly multiple times


这篇关于Windows窗体中Treeview中的Aftercheck和AfterSelect事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆