Tengo una subclase de System.Windows.Forms.TreeView
que se "vincula" manualmente a un conjunto de datos jerárquicos. Quiero que el usuario pueda editar las etiquetas del árbol y hacer que los cambios se reflejen en los datos. Así que me puse a LabelEdit
verdadera y OnAfterLabelEdit
hizo caso omiso a la suma de:¿Puedo insertar nodos en un TreeView durante AfterLabelEdit sin comenzar a editarlos?
protected override void OnAfterLabelEdit(NodeLabelEditEventArgs e)
{
base.OnAfterLabelEdit(e);
TreeNode node = e.Node;
if (PassesSomeValidation(e.Label))
{
MyDataNode dataNode = node.Tag as MyDataNode;
dataNode.SomeBoundValue = e.Label;
int oldIndex = node.Index;
int newIndex = RepositionChangedDataNode(dataNode);
TreeNode parent = node.Parent;
parent.Nodes.RemoveAt(oldIndex);
parent.Nodes.Insert(newIndex, node);
}
else
{
e.CancelEdit = true;
}
}
RepositionChangedDataNode()
re-ordena los datos y devuelve el índice en el que el nodo de cambio se movió después de la clasificación. Esperaba poder mover el nodo editado para reflejar este movimiento.
El problema es que esto hace que el nodo permanezca en modo de edición! Intenté llamar al EndEdit()
, cloné el nodo antes de insertarlo, configurando LabelEdit
en falso y devolviéndolo a verdadero, envolviendo el cambio en BeginUpdate()
/EndUpdate()
, y varias combinaciones de estas ideas, pero ninguna de ellas tiene ningún efecto.
El culpable parece ser la inserción. Incluso si intento insertar un nuevo nuevo nodo, entrará en modo de edición inmediatamente.
Entonces, ¿hay alguna manera de hacer que TreeView
no se comporte de esta manera? Y si no, ¿hay una buena solución?
Algunas ideas que hemos considerado:
- Establecer un TreeViewNodeSorter personalizado. Sin embargo, preferiría no tener que ordenar mis datos dos veces.
- Establezca un indicador y demore el paso de quitar e insertar hasta algún punto después de AfterLabelEdit. Funciona para hacerlo durante WndProc, pero esto se siente como un gran error que de alguna manera puede fallar.
Uso
BeginInvoke()
para empujar el paso de quitar a insertar de nuevo en la cola de mensajes, así:BeginInvoke(new MethodInvoker(delegate( { parent.Nodes.RemoveAt(oldIndex); parent.Nodes.Insert(newIndex, node); }));
Esto funciona y parece más limpio para mí que # 2, pero sé que esto probablemente no es la forma en
BeginInvoke()
estaba destinado para ser utilizado, y que puede tener repercusiones que mi muy limitado conocimiento del mensaje bomba no puede predecir.
Tengo el mismo problema: ¿qué terminaste haciendo? – Handleman
Fui con la idea n. ° 3 por el momento. Parece estar funcionando bien hasta ahora. –
Acabo de tener un problema similar al intentar ordenar TreeView en el evento AfterLabelEdit. Usé una solución similar a la tuya, y funcionó bien. Probablemente sea un error en TreeView ... –