2011-07-06 7 views
6

Estoy usando WinForms TreeView y la reacción al evento AfterLabelEdit. Aquí está el fragmento de código:Problema con TreeNode.BeginEdit()

if (e.Label.Contains("|")) 
{ 
    if (WantAutofix()) 
    { 
    label = e.Label.Replace('|', '_'); 
    } 
    else 
    { 
    e.CancelEdit = true; 
    e.Node.BeginEdit(); 
    return; 
    } 
} 

El problema es que cuando el usuario no desea corrección automática de mal carácter, el nodo no permanece en el modo de edición. Cualquier forma de arreglar esto?

Respuesta

2

Algunas cosas a tener en cuenta:

  1. El evento AfterLabelEdit siempre termina el modo de edición después de que se levantó , incluso si llama al BeginEdit en el medio de su manejador de eventos. Puede usar TreeView.BeginInvoke para "avanzar" haciendo que EditMode se inicie nuevamente después de que TreeView haga su trabajo. (NOTA: esto no crea un nuevo hilo o condición de carrera, simplemente retrasa el método para 1 mensaje de ventana.) Hay más información sobre algunos de los problemas con este evento here (aunque sugiere lo que creo que es un peor solución).
  2. e.Label es null si el usuario no hizo ningún cambio, por lo que cuando "saltamos" con BeginInvoke, es como si el usuario no hiciera ningún cambio, por lo que también tenemos que manejar ese caso.
  3. BeginInvoke es una solución aceptable en este caso, debe encontrarlo como muy confiable en esta situación.

Esto funciona muy bien para mí, probado con .NET 2.0:

private void treeView1_AfterLabelEdit(object sender, NodeLabelEditEventArgs e) 
    { 
     //we have to handle both the first and future edits 
     if ((e.Label != null && e.Label.Contains("|") || (e.Label == null && e.Node.Text.Contains("|")))) 
     { 
      if (WantAutofix()) 
      { 
       e.CancelEdit = true; 

       if(e.Label != null) 
        e.Node.Text = e.Label.Replace('|', '_'); 
       else 
        e.Node.Text = e.Node.Text.Replace('|', '_'); 
      } 
      else 
      { 
       //lets the treeview finish up its OnAfterLabelEdit method 
       treeView1.BeginInvoke(new MethodInvoker(delegate() { e.Node.BeginEdit(); })); 
      } 
     } 

    } 

    private bool WantAutofix() 
    { 
     return MessageBox.Show("You entered a |, you want me to AutoFix?", String.Empty, MessageBoxButtons.YesNo) == DialogResult.Yes; 
    } 
0

Usted podría intentar hacer el BeginEdit() se producen de forma asíncrona:

private void treeView1_AfterLabelEdit(object sender, NodeLabelEditEventArgs e) 
    { 
     if (e.Label.Contains("|")) 
     { 
      if (WantAutofix()) 
      { 
      } 
      else 
      { 
       e.CancelEdit = true; 
       BeginInvoke(new ActionDelegate(new NodeBeginEditAsync(e.Node).Execute)); 
       return; 
      } 
     } 
    } 
public class NodeBeginEditAsync 
{ 
    private readonly TreeNode _node; 

    public NodeBeginEditAsync(TreeNode node) 
    { 
     _node = node; 
    } 

    public void Execute() 
    { 
     _node.BeginEdit(); 
    } 
} 

public delegate void ActionDelegate(); 

De esta forma el CancelEdit se le da la oportunidad de completar antes de una nueva BeginEdit intenta asumir el control.

+0

No es realmente una opción: Consumo .NET 2.0, y esto no es una solución fiable. – Migol

+0

¿Por qué piensas eso? (No puede usar la sintaxis de Action() tal vez, pero BeginInvoke funciona con certidumbre en .NET 2.0) – jlew

+0

Simple. Si esta solución funciona, entonces tenemos una condición de carrera: el hilo se crea y se ejecuta antes de CancelEdit - MALO, después de él - BUENO. – Migol

0

Uso EndEdit y reemplazar el "mal carácter", si el usuario quiere corrección automática

+0

No me entendiste. Quiero permanecer en el modo de edición si quiere arreglarlo él mismo. Ahí está el problema. – Migol

0
try this...  
TreeNode node = tv.SelectedNode; 
        if (tv.SelectedNode.Parent == null) 
        { 
         node.TreeView.LabelEdit = false; 
        } 
        else 
        { 
         node.Text = FieldName.Text; 
         if (node == null) { return; } 
         node.TreeView.LabelEdit = true; 
         node.BeginEdit(); 
        }