ejemplo change c# .net winforms events textchanged

c# - change - ¿Por qué esto no está causando un ciclo infinito de eventos?



ejemplo textchanged c# (4)

Es bastante fácil de verificar.

Primero, reemplace ambos controles de cuadro de texto con

class T : TextBox { public override string Text { get { return base.Text; } set { base.Text = value; } } }

En segundo lugar, establezca el punto de interrupción en setter. Agregue estas expresiones a la ventana de observación:

  • Nombre
  • Texto
  • valor

En tercer lugar, inicie la aplicación, copie ''123'' de algún lado y péguelo en el primer cuadro de texto. Aquí va:

1er descanso:

  • Nombre: "mirrorText"
  • Texto: ""
  • valor: "321"

2º descanso:

  • Nombre: "realText"
  • Texto: "123"
  • valor: "123"

Tercero ... Ups, ya no se rompe. Para detectar por qué tenemos que ir más profundo. Mire el sourcesource: el cuadro de texto setter no hace nada inusual, pero el de TextBoxBase parece interesante :

set { if (value != base.Text) { // Gotcha! base.Text = value; if (IsHandleCreated) { // clear the modified flag SendMessage(NativeMethods.EM_SETMODIFY, 0, 0); } } }

Entonces, como hvd ya respondió, la razón es que el cuadro de texto no eleva TextChanged si los valores antiguos y nuevos son los mismos. No creo que el comportamiento cambie, al menos para las formas de ganar. Pero si quieres una solución más robusta, aquí está:

private void RunOnce(ref bool flag, Action callback) { if (!flag) { try { flag = true; callback(); } finally { flag = false; } } } private bool inMirror; private void realText_TextChanged(object sender, EventArgs e) { RunOnce(ref inMirror, () => { mirrorText.Text = mirror(realText.Text); }); } private void mirrorText_TextChanged(object sender, EventArgs e) { RunOnce(ref inMirror, () => { realText.Text = mirror(mirrorText.Text); }); } private string mirror(string text) { return new string(text.Reverse().ToArray()).Replace("/n/r", "/r/n"); }

PS mirror () fallará en pares de sustitución. Here''re algunas soluciones.

Tengo una aplicación simple que invierte el texto escrito en otro cuadro de texto. El truco es que puedes modificar cualquiera de los cuadros de texto y los cambios se reflejarán (literalmente) en el otro.

Escribí este código, creyendo que causaba problemas.

private void realText_TextChanged(object sender, EventArgs e) { mirrorText.Text = mirror(realText.Text); } private void mirrorText_TextChanged(object sender, EventArgs e) { realText.Text = mirror(mirrorText.Text); } private string mirror(string text) { return new string(text.Reverse().ToArray()).Replace("/n/r", "/r/n"); }

Luego lo probé, creyendo que causaría un bucle infinito ( realText cambia a mirrorText , sucede otro evento, mirrorText cambia a realText , etc.). Sin embargo, nada excepto el comportamiento previsto sucedió.

Por supuesto que estoy feliz por esto, podría dejarlo aquí. ¿O podría?

Estoy bastante seguro de que se supone que el evento TextChanged se TextChanged que se TextChanged el Text . ¿Es este comportamiento previsto de alguna protección de error en los eventos, o simplemente tuve suerte? ¿Puede este código funcionar mal en otra computadora, con otras configuraciones de compilación, etc.? Se puede arreglar fácilmente:

private void realText_TextChanged(object sender, EventArgs e) { if (realText.Focused) { mirrorText.Text = Mirror(realText.Text); } }

Probablemente lo haga de todos modos para estar seguro, pero ¿es necesario verificar esto? (Ni siquiera voy a preguntar si es recomendable).


La razón por la que no causa un bucle es que comprueba si la propiedad Text realmente cambió, es decir, si el nuevo valor no es igual al valor anterior. En su caso, la función mirror invierte, lo que lleva al mismo texto después de dos pasadas.


Según los comentarios, y como ya se respondió, el evento TextChanged no se TextChanged cuando establece la propiedad Text en el valor que ya tiene.

No está claro si esto es algo en lo que puede confiar de manera segura. Es una optimización sensata, y me sorprendería mucho que las versiones futuras de .NET Framework lo abandonen, pero no puedo hablar de versiones anteriores ni de implementaciones de terceros (Mono).

Para estar absolutamente seguro, no utilizaría el control de Focused que hizo en su pregunta. Haría exactamente lo que hace el Text setter ahora.

private void realText_TextChanged(object sender, EventArgs e) { var newMirrorText = Mirror(realText.Text); if (mirrorText.Text != newMirrorText) mirrorText.Text = newMirrorText; }

Esto tiene la misma ventaja de evitar la recursión infinita, pero juega mejor con otro código que puedes poner en tu forma que cambia el texto como resultado de algún otro evento.


Si textbox tiene un texto e intentamos cambiarlo con el mismo texto, el evento TextChange no se activa porque el texto nuevo es el mismo que el anterior. En su código, el evento realText_TextChanged invierte el texto y cambia el mirrorText con él. El evento mirrorText_TextChanged invierte el texto e intenta cambiar el texto real. El texto real ya tiene este texto y no plantea el evento realText_TextChanged.