Alterar o valor de um nó em um TreeView assíncrona
-
07-07-2019 - |
Pergunta
Eu tenho um treeview usando trabalho de fundo para adicionar nós quando você expandir qualquer. I exibir uma mensagem "Carregando .." após a expandir e removê-lo após os nós são carregados. Ele funciona muito bem e tudo. Agora eu quero mudar a mensagem de carregamento com "Loading ... node n / n". Eu era capaz de fazer isso, mas o problema é que esta mensagem não é exibida (atualizado para) enquanto fazer a operação nó acrescentando mas após ter sido concluída . Eu não conseguia descobrir o que estou fazendo de errado e espero que alguém pode lançar uma luz sobre isso.
Aqui está o meu código. Eu depurado método SetValue e atualiza corretamente o texto do nó, mas não exibido até o final da operação ..
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
}
Solução
A (principal) problema é com o seu bw_ProgressChanged. Não necessidade de invocar qualquer coisa porque é o trabalho do BGW para sincronizar o ProgressChanged. Eu não dói, mas perder a invocação de qualquer maneira.
A razão que você não vê quaisquer mudanças é a falta de um 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
}
Há um outro problema em bw_DoWork (), você usar Invoke nas AddSubNodes () método. Como resultado de 99% de seu código é executado inteiramente no segmento principal e sua solução não é multi-threaded em tudo.
eu faria algo como:
//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;
}
E, em seguida, em bw_RunWorkerCompleted, adicionar rapidamente os elementos de newNodes a 't'.