none
关于WinForm中TreeView的复选框问题,请教··· RRS feed

  • 问题

  •         private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
            {
                this.treeView1.SelectedNode = e.Node;
                if (e.Node.Checked == true)
                {
                    e.Node.Checked = false;
                }
                else
                {
                    e.Node.Checked = true;
                }

              
            }


            private void treeView1_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
            {
                this.treeView1.SelectedNode = e.Node;
                if (e.Node.Checked == true)
                {
                    e.Node.Checked = false;
                }
                else
                {
                    e.Node.Checked = true;
                }
            }

            private void treeView1_BeforeCheck(object sender, TreeViewCancelEventArgs e)
            {
                this.treeView1.SelectedNode = e.Node;
            }

            private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
            {
                this.treeView1.SelectedNode = e.Node;
            }

    在单击节点的文本值的时候,复选框的选中状态会变化,但是我直接点击复选框的时候,其选中状态没有发生变化,
    请教下怎么解决!谢谢

    2009年11月10日 3:31

答案

  • 你好!

    刚才的问题换了个思路已解决了。

    private bool hasBreakNodeClick = false;
    private bool hasAfterCheck = false;
    
    private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
    {
        if (this.hasBreakNodeClick)
        {
            this.hasBreakNodeClick = false;
            return;
        }
        this.hasAfterCheck = true;
        this.treeView1.SelectedNode = e.Node;
        if (e.Node.Checked == true)
        {
            e.Node.Checked = false;
        }
        else
        {
            e.Node.Checked = true;
        }
    }
    
    private void treeView1_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
    {
        this.treeView1.SelectedNode = e.Node;
        if (e.Node.Checked == true)
        {
            e.Node.Checked = false;
        }
        else
        {
            e.Node.Checked = true;
        }
    }
    
    private void treeView1_BeforeCheck(object sender, TreeViewCancelEventArgs e)
    {
        this.treeView1.SelectedNode = e.Node;
    }
    
    private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
    {
        this.treeView1.SelectedNode = e.Node;
        if (this.hasAfterCheck)
        {
            this.hasAfterCheck = false;
            return;
        }
        this.hasBreakNodeClick = true;
    }

    其它问题:

    1 MessageBox 有暂停的的效果,可能是由这个原因所致。
    2 通过两个事件来处理点击文件是 NodeClick 点击单选框是 BeforeCheck ,在事件中根据 Node 的选中状态来确定是否选中或取消选中(注意区分事件顺序)。
    3 用个数组来记录那些节点是默认选中的节点,取消选择时判断节点是否在数组中来确定是否能取消选择。


    知识改变命运,奋斗成就人生!
    • 已标记为答案 天驰 2009年11月11日 7:30
    2009年11月10日 7:15
    版主

全部回复

  • 你好!

    问题是由于 AfterCheck 后又引发了 NodeClick 反致。解决方法如下:

    private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
    {
        if (this.sysAction) return;
        this.treeView1.SelectedNode = e.Node;
        if (e.Node.Checked == true)
        {
            e.Node.Checked = false;
        }
        else
        {
            e.Node.Checked = true;
        }
    }
    
    private void treeView1_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
    {
        if (this.sysAction) return;
        this.treeView1.SelectedNode = e.Node;
        if (e.Node.Checked == true)
        {
            e.Node.Checked = false;
        }
        else
        {
            e.Node.Checked = true;
        }
    }
    
    private void treeView1_BeforeCheck(object sender, TreeViewCancelEventArgs e)
    {
        this.treeView1.SelectedNode = e.Node;
    }
    
    bool sysAction = false;
    
    private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
    {
        try
        {
            this.sysAction = true;
            this.treeView1.SelectedNode = e.Node;
        }
        finally
        {
            this.RunDelayDelegate(delegate
            {
                this.sysAction = false;
            }, 800);
        }
    }
    
    public delegate void ClientDelegate();
    
    /// <summary>
    /// 延时执行
    /// </summary>
    /// <param name="d"></param>
    /// <param name="delaySpan"></param>
    public void RunDelayDelegate(ClientDelegate d, int delaySpan)
    {
        using (BackgroundWorker backgroundWorker = new BackgroundWorker())
        {
            backgroundWorker.DoWork += new DoWorkEventHandler(delegate(object o, DoWorkEventArgs workerEventArgs)
            {
                Thread.Sleep(delaySpan);
            });
    
            backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(delegate(object o, RunWorkerCompletedEventArgs e)
            {
                if (d != null)
                    this.BeginInvoke(d);
            });
    
            backgroundWorker.RunWorkerAsync();
        }
    }


    知识改变命运,奋斗成就人生!
    2009年11月10日 5:34
    版主
  • 刚才试了一下,还是有一些问题

    第一,我点击一个节点的显示的Text上面,他被选中,然后不进行别的操作,继续点击别的,在2-3次点击后,问题出现;继续点击下去,点击一个节点,状态没变化,再点另一个,状态改变,然后下一个又没变化。(只是点击复选框的话,出现的问题是,在点击多次以后,会突然出现一次点击失效)

    这个怎么解决???

    还有几个问题,
    第一:我在我的原始代码的
    private void treeView1_BeforeCheck(object sender, TreeViewCancelEventArgs e)
    private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
    里放一个MessageBox.发现,一切运行都是正常,能帮我解释一下原因吗?

    第二:如果我只是把TreeView的复选框显示出来,但是让它的点击失效,只能在点击节点的Text值的时候改变其选中状态,这个又应该怎么解决。

    第三:如果我在给TreeView加载子节点的时候,给了它一个的默认选中状态,例如把某一个节点设置成了选中的状态,现在我要求的是,这个节点的选中状态不能再被更改,这个又应该如何去做呢?

    问题可能有点多,习惯性的,麻烦了,谢谢!


    2009年11月10日 6:06
  • 你好!
         建议明确一下你的问题,你想实现怎样的效果呢?
    周雪峰
    2009年11月10日 6:20
    版主
  • 你好!

    刚才的问题换了个思路已解决了。

    private bool hasBreakNodeClick = false;
    private bool hasAfterCheck = false;
    
    private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
    {
        if (this.hasBreakNodeClick)
        {
            this.hasBreakNodeClick = false;
            return;
        }
        this.hasAfterCheck = true;
        this.treeView1.SelectedNode = e.Node;
        if (e.Node.Checked == true)
        {
            e.Node.Checked = false;
        }
        else
        {
            e.Node.Checked = true;
        }
    }
    
    private void treeView1_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
    {
        this.treeView1.SelectedNode = e.Node;
        if (e.Node.Checked == true)
        {
            e.Node.Checked = false;
        }
        else
        {
            e.Node.Checked = true;
        }
    }
    
    private void treeView1_BeforeCheck(object sender, TreeViewCancelEventArgs e)
    {
        this.treeView1.SelectedNode = e.Node;
    }
    
    private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
    {
        this.treeView1.SelectedNode = e.Node;
        if (this.hasAfterCheck)
        {
            this.hasAfterCheck = false;
            return;
        }
        this.hasBreakNodeClick = true;
    }

    其它问题:

    1 MessageBox 有暂停的的效果,可能是由这个原因所致。
    2 通过两个事件来处理点击文件是 NodeClick 点击单选框是 BeforeCheck ,在事件中根据 Node 的选中状态来确定是否选中或取消选中(注意区分事件顺序)。
    3 用个数组来记录那些节点是默认选中的节点,取消选择时判断节点是否在数组中来确定是否能取消选择。


    知识改变命运,奋斗成就人生!
    • 已标记为答案 天驰 2009年11月11日 7:30
    2009年11月10日 7:15
    版主
  • 一共是4个问题,

    第一个问题:就是刚开始发的帖子上说的,X.X.Y给了一段代码,但是我试验的时候出现了一些问题,
    在第二个帖子里刚开始的时候说了



    第二个问题:是我在第一个帖子的我的原始代码上做的试验时候,出现的
    private void treeView1_BeforeCheck(object sender, TreeViewCancelEventArgs e)
    private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
    里任意位置放一个MessageBox.运行发现,一切运行都是正常,(为什么加了MessageBox就正常了)能帮我解释一下原因吗?


    第三个问题:和上面的代码没有关系,
    如果我只是把TreeView的复选框显示出来,但是让它的点击失效,只能在点击节点的Text值的时候改变其选中状态,这个又应该怎么解决。


    第四个为题:和上面的代码没有关系,
    如果我在给TreeView加载子节点的时候,给了它一个的默认选中状态,例如把某一个节点设置成了选中的状态,现在我要求的是,这个节点的选中状态不能再被更改,这个又应该如何去做呢?


    可能表述不大清楚,麻烦了!

    2009年11月10日 7:20