不能在TreeView (WinForms)中展开节点

本文关键字:节点 WinForms TreeView 不能 | 更新日期: 2023-09-27 18:15:15

我以编程方式填充TreeView(在不同的线程中,如果它重要的话)。

我希望在TreeView加载到window时扩展第一层节点。我几乎到处都尝试过(在工作线程中,在主线程中,在Form.Load, Form.Shown等的事件处理程序中),但TreeView仍然崩溃。

我做错了什么?

treeView.UpdateTree((object tree) => {
    treeView.Nodes[0].Nodes.Add(text);
});
public static void UpdateTree(this Control ctrl, Action<object> code) {
    if (ctrl.InvokeRequired) {
        ctrl.BeginInvoke(code, (TreeView)ctrl);
    }
    else {
        code.Invoke((TreeView)ctrl);
    }
}

更新2

private void btnFillTree_Click(object sender, EventArgs e) {
    ......
    treeDirectoryContents.Nodes.Add("GeneralFolder");
    ......
    //there I create Thread() that fills treeDirectoryContents
    ......
    treeDirectoryContents.ExpandAll();
}

不能在TreeView (WinForms)中展开节点

据我所知…. NET 3.5)你不能从不同的线程访问GUI元素(你可以准备一些数据,但必须从主线程访问TreeView.Nodes -使用Control.BeginInvoke…你也可以检查Control.InvokeRequired)。

填满所有节点后,可以直接执行

foreach (TreeNode node in treeView) node.Expand()

EDIT after UPDATE2:

  1. 节点只有在有子节点时才能扩展。
  2. 控件只能从主线程访问(检查Control.InvokeRequired)
  3. BeginInvoke()是异步的(不等待)而Invoke()是同步的(像BeginInvoke + EndInvoke)
  4. 永远不要从主线程调用Thread.Join()(使用BackgroundWorker.IsBusy或模仿一些状态变量,例如bool done = false; thread.Start(); while(!done) Application.DoEvents()

来自MSDN的示例:

// Start the download operation in the background. 
this.backgroundWorker1.RunWorkerAsync();
// Disable the button for the duration of the download. 
this.downloadButton.Enabled = false;
// Once you have started the background thread you  
// can exit the handler and the application will  
// wait until the RunWorkerCompleted event is raised. 
// Or if you want to do something else in the main thread, 
// such as update a progress bar, you can do so in a loop  
// while checking IsBusy to see if the background task is 
// still running. 
while (this.backgroundWorker1.IsBusy)
{
    progressBar1.Increment(1);
    // Keep UI messages moving, so the form remains  
    // responsive during the asynchronous operation.
    Application.DoEvents();
}

EDIT -我认为应该如何做(使用线程)

using System;
using System.Threading;
using System.Windows.Forms;
class MyForm : Form {
    public static void Main() {
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new MyForm());
    }
    TreeView tree = new TreeView() { Dock = DockStyle.Fill };
    MyForm() {
        Controls.Add(tree);
        tree.Nodes.Add("Loading...");
    }
    protected override void OnLoad(EventArgs e) {
        new Thread(Fill).Start();
        base.OnLoad(e);
    }
    void Create(string text) {
        if (InvokeRequired) Invoke(new Action<string>(this.Create), text);
        else tree.Nodes[0].Nodes.Add(text);
    }
    void Finish() {
        if (InvokeRequired) Invoke(new Action(this.Finish));
        else {
            tree.Nodes[0].Text = "The Nodes";
            tree.ExpandAll();
        }
    }
    void Fill() {
        for (int i = 0; i < 10; i++) {
            Create("Node #" + i.ToString());
            Thread.Sleep(100);
        }
        Finish();
    }
}