我以编程方式填写TreeView
(如果重要的话,请在不同的帖子中填写)。
我希望在TreeView
加载到窗口时扩展第一级节点。我几乎到处都尝试过(在工作线程,主线程,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();
}
答案 0 :(得分:5)
据我所知(.NET 3.5),您无法从不同的线程访问GUI元素(您可以准备一些数据,但必须仅从主线程访问TreeView.Nodes
- 请使用Control.BeginInvoke
...你也可以查看Control.InvokeRequired
)。
填写所有节点后,您可以
foreach (TreeNode node in treeView) node.Expand()
UPDATE2后编辑:
Control.InvokeRequired
)Invoke()
是同步的(如BeginInvoke + EndInvoke)时,BeginInvoke()是异步的(不等待)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();
}
编辑 - 我应该怎么做(使用主题)
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();
}
}