Tengo una aplicación de prueba muy simple para jugar con Windows Phone 7. Acabo de agregar un TextBox
y un TextBlock
a la plantilla de interfaz de usuario estándar. El único código personalizado es el siguiente:
public partial class MainPage : PhoneApplicationPage
{
public MainPage()
{
InitializeComponent();
}
private int counter = 0;
private void TextBoxChanged(object sender, TextChangedEventArgs e)
{
textBlock1.Text += "Text changed " + (counter++) + "\r\n";
}
}
El TextBox.TextChanged
evento está conectado a TextBoxChanged
XAML:
<TextBox Height="72" HorizontalAlignment="Left" Margin="6,37,0,0"
Name="textBox1" Text="" VerticalAlignment="Top"
Width="460" TextChanged="TextBoxChanged" />
Sin embargo, cada vez que presiono una tecla cuando se ejecuta en el emulador (ya sea el teclado en pantalla o el físico, después de presionar Pausa para habilitar este último), aumenta el contador dos veces, mostrando dos líneas en el TextBlock
. Todo lo que he intentado muestra que el evento realmente se está disparando dos veces y no tengo idea de por qué. He verificado que solo se suscribe una vez: si me doy de baja en el MainPage
constructor, no pasa nada (en el bloque de texto) cuando el texto cambia.
Probé el código equivalente en una aplicación Silverlight normal y no ocurrió allí. No tengo un teléfono físico para reproducir esto en este momento. No he encontrado ningún registro de que esto sea un problema conocido en Windows Phone 7.
¿Alguien puede explicar qué estoy haciendo mal, o debería informar de esto como un error?
EDITAR: Para reducir la posibilidad de que esto se deba a tener dos controles de texto, he intentado eliminar por TextBlock
completo y cambiar el método TextBoxChanged para solo incrementar counter
. Luego ejecuté el emulador, escribí 10 letras y luego puse un punto de interrupción en la counter++;
línea (solo para deshacerme de cualquier posibilidad de que irrumpir en el depurador esté causando problemas), y se muestra counter
como 20.
EDITAR: Ahora he preguntado en el foro de Windows Phone 7 ... veremos qué sucede.
fuente
textBox1.Text
presiono "h" y lo visualizo como parte de la adición textBlock1, mostrará "h" en ambas líneas.TextChangedEventArgs
realmente no tiene mucho disponible, solo elOriginalSource
, que siempre es nulo.Respuestas:
La razón por la
TextChanged
que el evento se dispara dos veces en WP7 es un efecto secundario de cómoTextBox
se ha diseñado para el aspecto de Metro.Si edita la
TextBox
plantilla en Blend, verá que contiene una secundariaTextBox
para el estado deshabilitado / solo lectura. Esto provoca, como efecto secundario, que el evento se dispare dos veces.Puede cambiar la plantilla para eliminar el extra
TextBox
(y los estados asociados) si no necesita estos estados, o modificar la plantilla para lograr un aspecto diferente en el estado deshabilitado / de solo lectura, sin usar un secundarioTextBox
.Con eso, el evento se disparará solo una vez.
fuente
Yo iría por el error, principalmente porque si pones los eventos
KeyDown
yKeyUp
allí, muestra que se activan solo una vez (cada uno de ellos) pero elTextBoxChanged
evento se activa dos veces.fuente
TextInput
?" No estoy familiarizado conTextInput
...Eso me suena como un error. Como solución alternativa, siempre puede usar Rx
DistinctUntilChanged
. Hay una sobrecarga que le permite especificar la clave distinta.Este método de extensión devuelve el evento TextChanged observable pero omite duplicados consecutivos:
Una vez que se corrige el error, simplemente puede eliminar la
DistinctUntilChanged
línea.fuente
¡Agradable! Encontré esta pregunta al buscar un problema relacionado y también encontré esta cosa molesta en mi código. En mi caso, el evento doble consume más recursos de CPU. Entonces, arreglé mi cuadro de texto de filtro en tiempo real con esta solución:
fuente
Creo que esto siempre ha sido un error en Compact Framework. Debe haber sido transferido a WP7.
fuente
Claro que me parece un error, si está tratando de generar un evento cada vez que el texto cambia, podría intentar usar un enlace bidireccional en su lugar, desafortunadamente esto no generará eventos de cambio por pulsación de tecla (solo cuando el campo pierde el enfoque). Aquí hay una solución alternativa si la necesita:
fuente
textBlock1.Text
cambio, aunque lo intentaré. (La solución que iba a intentar era hacer que mi manejador de eventos tuviera estado, recordando el texto anterior. Si no ha cambiado, ignóralo :)Descargo de responsabilidad: no estoy familiarizado con los matices de xaml y sé que esto suena ilógico ... pero de todos modos, mi primer pensamiento es intentar pasar simplemente como eventos simples en lugar de cambios de texto. No tiene sentido, pero ¿podría ayudar? Parece que cuando he visto disparos dobles como este antes, se debe a un error o debido a que de alguna manera 2 agregan llamadas al controlador de eventos que ocurren detrás de escena ... ¿No estoy seguro de cuál?
Si necesita rápido y sucio, nuevamente, no tengo experiencia con xaml, mi siguiente paso sería simplemente omitir xaml para ese cuadro de texto como una solución rápida ... haga ese cuadro de texto totalmente en c # por ahora hasta que pueda identificar el error o código complicado ... es decir, si necesita una solución temporal.
fuente
No creo que sea un error ... Cuando asigna el valor a una propiedad de texto dentro del evento textchanged, el valor del cuadro de texto se cambia, lo que volverá a llamar al evento de cambio de texto ...
intente esto en la aplicación Windows Forms, es posible que obtenga un error
"Se produjo una excepción no controlada del tipo 'System.StackOverflowException' en System.Windows.Forms.dll"
fuente
StefanWick tiene razón, considere usar esta plantilla
fuente
Es un tema antiguo, pero en lugar de cambiar la plantilla (eso no funciona para mí, no veo el otro cuadro de texto con Blend) puede agregar boolean para verificar si el evento ya hizo la función o no.
Soy consciente de que NO es la forma perfecta, pero creo que es la forma más sencilla de hacerlo. Y funciona.
fuente