无法在TreeView(WinForms)中展开节点 [英] Can't expand nodes in TreeView (WinForms)
问题描述
我正在以编程方式填充TreeView
(如果重要的话,将其填充在其他线程中).
I'm filling TreeView
programmatically (in different thread if it matters).
我希望在TreeView
加载到窗口时扩展第一级节点.我几乎在所有地方都尝试过(在工作线程,主线程中,在Form.Load
,Form.Shown
的事件处理程序中),但是TreeView
仍然崩溃.
I want the first level of nodes to be expanded when TreeView
loads to window. I've tried almost everywhere (in worker thread, in main thread, in event handlers of Form.Load
, Form.Shown
etc.), but TreeView
is still collapsed.
我在做什么错了?
更新
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();
}
推荐答案
据我所知(.NET 3.5),您无法访问来自不同线程的GUI元素(可以准备一些数据,但只能从主线程访问TreeView.Nodes
-为此使用Control.BeginInvoke
...您也可以检查Control.InvokeRequired
).
As far I know (.NET 3.5) you cannot acces GUI elements from different thread (you can prepare some data but must access TreeView.Nodes
from main thread only - use Control.BeginInvoke
for that ... you can as well check Control.InvokeRequired
).
填满所有节点后,您就可以做
After filling all the nodes you can just do
foreach (TreeNode node in treeView) node.Expand()
在UPDATE2之后进行
- 节点只有在有子节点时才可以扩展.
- 只能从主线程访问控件(请检查
Control.InvokeRequired
) - BeginInvoke()是异步的(不等待),而
Invoke()
是同步的(例如BeginInvoke + EndInvoke) - 请勿从主线程调用
Thread.Join()
(使用BackgroundWorker.IsBusy
或通过某些状态变量(例如bool done = false; thread.Start(); while(!done) Application.DoEvents()
)模仿
- Nodes can only be expanded when they have children.
- Controls can only be accessed from main thread (check
Control.InvokeRequired
) - BeginInvoke() is asynchronous (does not wait) while
Invoke()
is synchronous (like BeginInvoke + EndInvoke) - Never call
Thread.Join()
from main thread (useBackgroundWorker.IsBusy
or mimic that by some state variable e.g.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();
}
编辑-我该怎么做(使用线程)
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();
}
}
这篇关于无法在TreeView(WinForms)中展开节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!