【问题标题】:TreeView does not update when modified. Windows Forms修改时 TreeView 不会更新。 Windows 窗体
【发布时间】:2023-04-07 19:20:01
【问题描述】:

我有一个 Windows 窗体 C# 应用程序,它处理 TreeView 并使用单独的线程来更新它。 单击按钮启动更新:

    private void button3_Click(object sender, EventArgs e)
    {
        vc.ChangeTree(treeView1);
    }

ChangeTree() 在单独的线程中启动 UpdateTree() 以异步更新 TreeView。 在这里我只需要使用 Thread 即可:

    public void ChangeTree(TreeView tree)
    {
        Thread thread4 = new Thread(() => { UpdateTreeView(tree); });
        thread4.Name = "Thread 4";
        thread4.IsBackground = true;
        thread4.Start();
    }

UpdateTree() 只是调用 TreeView 并将另一棵树的节点添加到其中。请注意,没有耗时的操作。 GetTree() 只是返回另一个 TreeView:

    private void UpdateTreeView(TreeView tree)
    {
        if (tree.InvokeRequired)
        {
            tree.Invoke((MethodInvoker)delegate
            {
                UpdateTreeView(tree);
            });
        }
        else
        {
            tree.Nodes.Clear();
            foreach (var node in GetTree().Nodes)
            {
                tree.Nodes.Add(node as TreeNode);
            }
            //Application.DoEvents(); // doesn't help
        }
    }

问题是它实际上将节点添加到树中,但表单没有显示它。单击按钮后,我检查了treeView1.Nodes。它包含我需要的节点。

根据我的搜索,Application.DoEvents() 没有帮助,即使它可能。 treeView1.Refresh() 也没有。

如果我单击按钮两次,treeView1 会按我的计划更新。但我不知道为什么,显然我不需要这种行为。

所以问题来了。如何让它一键更新?


事实证明,TreeNode 不能被多个 TreeView 使用。

解决方法我发现是使用treeNode.Clone():

tree.Nodes.Add((node as TreeNode).Clone() as TreeNode);

但是我仍然不明白为什么最初的代码可以工作,尽管它花了两次。

【问题讨论】:

  • 您在foreach 循环之后尝试过tree.Invalidate() 吗?
  • @Übercoder 是的,没有结果

标签: c# multithreading winforms treeview


【解决方案1】:

我怀疑一个 TreeNode 不能从一个 TreeView 更改为另一个

这是我的有效测试代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            ChangeTree(treeView1);
        }

        public void ChangeTree(TreeView tree)
        {
            Thread thread4 = new Thread(() => { UpdateTreeView(tree); });
            thread4.Name = "Thread 4";
            thread4.IsBackground = true;
            thread4.Start();
        }

        private void UpdateTreeView(TreeView tree)
        {
            if (tree.InvokeRequired)
            {
                tree.Invoke((MethodInvoker)delegate
                {
                    UpdateTreeView(tree);
                });
            }
            else
            {
                tree.Nodes.Clear();
                foreach (var node in GetTree())
                {
                    tree.Nodes.Add(node as TreeNode);
                }
            }
        }

        private List<TreeNode> GetTree()
        {
            var result = new List<TreeNode>();

            result.Add(new TreeNode("changed"));

            return result;
        }
    }
}

如果我把GetTree()函数改成

    private TreeView GetTree()
    {
        var result = new TreeView();

        result.Nodes.Add(new TreeNode("changed"));

        return result;
    }

然后将 UpdateTreeView 函数恢复为以前的样子,它的行为就像你描述的那样

【讨论】:

  • 原来TreeNode不能被多个TreeView使用。因此,为了做到这一点,我必须对其进行 treeNode.Clone() 或将 TreeNodes 存储在 TreeView 中。
【解决方案2】:

您是否尝试将焦点设置回树视图?使用 TreeView.Focus() 这会导致刷新。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-27
    • 1970-01-01
    • 1970-01-01
    • 2015-11-17
    • 2015-11-21
    • 1970-01-01
    相关资源
    最近更新 更多