[英]Changing the value of a node in an asynchronous TreeView
I have a treeview using BackGround worker to add nodes when you expand any. 我有一个使用BackGround worker的treeview,可以在您展开任何节点时添加节点。 I display a "Loading.." message after the expand and remove it after the nodes are loaded.
展开后显示“正在加载..”消息,并在加载节点后将其删除。 It works fine and all.
一切正常。 Now I want to change the loading message to "Loading...node n/n".
现在,我想将加载消息更改为“ Loading ... node n / n”。 I was able to do it but the problem is this message is not displayed(updated to) while doing the node adding operation but after it's completed .
我能够做到,但问题是在执行节点添加操作时,但在完成后,此消息未显示(更新为)。 I couldn't figure out what I'm doing wrong and I hope someone can shed a light on this.
我不知道自己在做什么错,希望有人能对此有所启发。
Here's my code. 这是我的代码。 I debugged SetValue method and it correctly updates the node text, but it doesn't displayed until the end of the operation..
我调试了SetValue方法,它正确更新了节点文本,但是直到操作结束才显示。
private void t_AfterExpand(object sender, NodeEventArgs e)
{
t.AppendNode(new object[] { "Loading.." }, e.Node);
bw.RunWorkerAsync(new object[] { e.Node });
}
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
t.Invoke(new MethodInvoker( () => AddSubNodes(e.Argument) ));
e.Result = e.Argument;
}
private void AddSubNodes(object arg)
{
object[] args = arg as object[];
TreeListNode parentNode = args[0] as TreeListNode;
int nodeCount = 10;
for (int i = 0; i < nodeCount; i++)
{
t.AppendNode(new object[] { "node cell text" }, parentNode);
bw.ReportProgress(i, new object[]{ parentNode, "node: " + i.ToString() + "/" + nodeCount.ToString()});
}
}
private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
object[] args = e.UserState as object[];
TreeListNode parentNode = args[0] as TreeListNode;
string percentMsg = args[1].ToString(); //node: n/n message
t.Invoke(new MethodInvoker(() => parentNode.Nodes[0].SetValue(0, percentMsg))); //change "Loading.." to "node: n/n"
//parentNode.Nodes[0].SetValue(0, mesaj);
}
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
object[] result = e.Result as object[];
TreeListNode node = result[0] as TreeListNode;
node.Nodes.RemoveAt(0); //remove loading text
}
The (main) problem is with your bw_ProgressChanged. (主要)问题与您的bw_ProgressChanged有关。 It does not need to Invoke anything because it is the Bgw's job to synchronize the ProgressChanged.
它不需要调用任何东西,因为Bgw的工作是同步ProgressChanged。 I doesn't hurt, but loose the Invoke anyway.
我没有受伤,但是无论如何都不要调用。
The reason you don't see any changes is the lack of an Update(). 您看不到任何更改的原因是缺少Update()。
private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
object[] args = e.UserState as object[];
TreeListNode parentNode = args[0] as TreeListNode;
string percentMsg = args[1].ToString(); //node: n/n message
parentNode.Nodes[0].SetValue(0, percentMsg); //change "Loading.." to "node: n/n"
parentNode.TreeView.Update(); // or Form.Update
}
There is another problem in bw_DoWork(), you use Invoke on the AddSubNodes() method. bw_DoWork()中还有另一个问题,您在AddSubNodes()方法上使用了Invoke。 As a result 99% of your code runs entirely on the main thread and your solution is not multi-threaded at all.
结果,您99%的代码完全在主线程上运行,并且您的解决方案根本不是多线程的。
I would do something like: 我会做类似的事情:
//untested
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
// t.Invoke(new MethodInvoker( () => AddSubNodes(e.Argument) ));
object[] args = arg as object[];
TreeListNode parentNode = e;
var newNodes = new List<TreeNode>();
int nodeCount = 10;
for (int i = 0; i < nodeCount; i++)
{
// t.AppendNode(new object[] { "node cell text" }, parentNode);
newNodes.Add(new object[] { "node cell text" }); // ???
bw.ReportProgress(i, new object[]{ parentNode, "node: " + i.ToString() + "/" + nodeCount.ToString()});
}
// e.Result = e.Argument;
e.Result = newNodes;
}
And then, in bw_RunWorkerCompleted, quickly add the elements of newNodes to 't'. 然后,在bw_RunWorkerCompleted中,将newNodes的元素快速添加到't'。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.