无法在TreeView(WinForms)中扩展节点

时间:2014-07-26 22:08:35

标签: c# .net multithreading winforms treeview

我以编程方式填写TreeView(如果重要的话,请在不同的帖子中填写)。

我希望在TreeView加载到窗口时扩展第一级节点。我几乎到处都尝试过(在工作线程,主线程,Form.LoadForm.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();
}

1 个答案:

答案 0 :(得分:5)

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

填写所有节点后,您可以

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

UPDATE2后编辑:

  1. 节点只有在有孩子时才能展开。
  2. 只能从主线程(检查Control.InvokeRequired
  3. 访问控件
  4. Invoke()是同步的(如BeginInvoke + EndInvoke)时,BeginInvoke()是异步的(不等待)
  5. 永远不要从主线程中调用Thread.Join()(使用BackgroundWorker.IsBusy或模仿某个状态变量,例如bool done = false; thread.Start(); while(!done) Application.DoEvents()
  6. 来自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();
    }
    

    编辑 - 我应该怎么做(使用主题)

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