• VS中使用TreeView的Checked属性问题


      VS中使用TreeView,当需要用到Checked属性,并需要同步子节点和父节点的Checked属性时,若使用AfterCheck事件会导致死循环,这里我使用的是NodeMouseClick事件。代码如下:

    private void treeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
    {
        if (e.Node == null)
            return;
        switch (e.Button)
        {
            case MouseButtons.Left: //左键
              //改变子节点的状态
              this.CheckChildNode(e.Node);
            //改变父节点的状态
              this.CheckParentNode(e.Node);
                break;
            default:
                break;
        }
    }
    
    private void CheckChildNode(TreeNode node)
    {
        if (node.Nodes.Count < 1)
        {
            return;
        }
        foreach (TreeNode childNode in node.Nodes)
        {
            if (childNode.Checked != node.Checked)
            {
                childNode.Checked = node.Checked;
                CheckChildNode(childNode);
            }
        }
    }
    
    private void CheckParentNode(TreeNode node)
    {
        if (node.Parent == null)
        {
            return;
        }
        TreeNode parentNode = node.Parent;
        for (int i = 0; i < parentNode.Nodes.Count; i++)
        {
            if (!parentNode.Nodes[i].Checked)
            {
                parentNode.Checked = false;
                CheckParentNode(parentNode);
                return;
            }
        }
        parentNode.Checked = true;
        CheckParentNode(parentNode);
    }

      但是,在如下图的情况下:若单击“节点1”的非Checkbox位置(即只是单击节点,并不改变Checked属性),会导致子节点的Checked属性全部被置为false。

                       

      因为,在单击节点的时候,触发了NodeMouseClick事件,而此时无法判断是否是在改变其Checked属性。笔者尝试在NodeMouseClick和AfterCheck事件中记录并判断当前是否是在改变点击节点的Checked属性,结果由于无法确定点击时先触发的是哪个事件,导致这个方法失败了。

      最后,笔者通过判断点击的位置来确定是否是在改变点击节点的Checked属性,解决了这一缺陷。修改后的代码如下:

    
    

    /// <summary>
    /// 0级树节点Checkbox有效范围的X的最小值
    /// </summary>
    private int TreeNodeZeroLevelCheckboxLocationXMin = 3;

    /// <summary>
    /// 0级树节点Checkbox有效范围的X的最大值
    /// </summary>
    private int TreeNodeZeroLevelCheckboxLocationXMax = 15;

    /// <summary>
    /// 相邻等级树节点Checkbox有效范围的X的差值
    /// </summary>
    private int TreeNodeNextLevelCheckboxDiffX = 0;

    private void Form1_Load(object sender, EventArgs e)
    {
        TreeNodeNextLevelCheckboxDiffX = this.treeView.Indent;
        TreeNodeZeroLevelCheckboxLocationXMin += TreeNodeNextLevelCheckboxDiffX;
        TreeNodeZeroLevelCheckboxLocationXMax += TreeNodeNextLevelCheckboxDiffX;
    }

    private void treeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
    {
        if (e.Node == null)
           
    return;
       
    switch (e.Button)
        {
           
    case MouseButtons.Left: //左键
               
    //判断点击位置是否为Checkbox的有效范围
                if (e.X <= TreeNodeZeroLevelCheckboxLocationXMax + e.Node.Level * TreeNodeNextLevelCheckboxDiffX
                   
    && e.X >= TreeNodeZeroLevelCheckboxLocationXMin + e.Node.Level * TreeNodeNextLevelCheckboxDiffX)
                {
                   
    //改变子节点的状态
                    this.CheckChildNode(e.Node);
                   
    //改变父节点的状态
                    this.CheckParentNode(e.Node);
                }
               
    break;
           
    default:
               
    break;
        }
    }

       代码中的三个常量是笔者测试出来的,其中this.treeView.Indent是指每个子树节点级别的缩进距离。测试发现只要在X的范围内点击节点就会改变Checked属性,Y的取值没有影响。

  • 相关阅读:
    Binary Trees
    [POJ] String Matching
    Tree
    Maxmum subsequence sum problem
    poj 2104 划分树
    poj 2486 树形dp
    poj 1848 树形dp
    hdu 4578 线段树
    hdu 4585 set应用
    hdu 2412 树形DP
  • 原文地址:https://www.cnblogs.com/hibernation/p/3503274.html
Copyright © 2020-2023  润新知