Tenho um aplicativo de teste muito simples para brincar com o Windows Phone 7. Acabei de adicionar um TextBox
e um TextBlock
ao modelo de IU padrão. O único código personalizado é o seguinte:
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";
}
}
O TextBox.TextChanged
evento está conectado ao TextBoxChanged
XAML:
<TextBox Height="72" HorizontalAlignment="Left" Margin="6,37,0,0"
Name="textBox1" Text="" VerticalAlignment="Top"
Width="460" TextChanged="TextBoxChanged" />
Porém, toda vez que pressiono uma tecla durante a execução do emulador (seja o teclado na tela ou o físico, tendo pressionado Pause para habilitar o último), ele incrementa o contador duas vezes, exibindo duas linhas no TextBlock
. Tudo o que experimentei mostra que o evento está realmente disparando duas vezes, e não tenho ideia do motivo. Eu verifiquei que ele só está sendo inscrito uma vez - se eu cancelar a inscrição no MainPage
construtor, nada acontece (ao bloco de texto) quando o texto muda.
Tentei o código equivalente em um aplicativo Silverlight regular e não ocorreu lá. Não tenho um telefone físico para reproduzir isso no momento. Não encontrei nenhum registro deste ser um problema conhecido no Windows Phone 7.
Alguém pode explicar o que estou fazendo de errado ou devo relatar isso como um bug?
EDIT: Para reduzir a possibilidade de isso ser reduzido a dois controles de texto, tentei remover o TextBlock
completamente e alterar o método TextBoxChanged para apenas incrementar counter
. Eu, em seguida, executar no emulador, digitado 10 letras e , em seguida, colocar um ponto de interrupção nacounter++;
linha (apenas para se livrar de qualquer possibilidade de invadir o depurador está causando problemas) - e mostra counter
como 20.
EDIT: Eu já perguntei no fórum do Windows Phone 7 ... vamos ver o que acontece.
fonte
textBox1.Text
como parte da adição textBlock1, ele mostrará "h" em ambas as linhas.TextChangedEventArgs
não tem muito disponível - apenas oOriginalSource
, que é sempre nulo.Respostas:
O motivo do
TextChanged
evento ser disparado duas vezes no WP7 é um efeito colateral de como oTextBox
foi projetado para a aparência do Metro.Se você editar o
TextBox
modelo no Blend, verá que ele contém umTextBox
para o estado desabilitado / somente leitura. Isso faz com que, como efeito colateral, o evento seja disparado duas vezes.Você pode alterar o modelo para remover os
TextBox
estados extras (e associados) se não precisar desses estados, ou modificar o modelo para obter uma aparência diferente no estado desativado / somente leitura, sem usar um secundárioTextBox
.Com isso, o evento será disparado apenas uma vez.
fonte
Eu iria para o bug, principalmente porque se você colocar os eventos
KeyDown
eKeyUp
lá, isso mostra que eles são disparados apenas uma vez (cada um deles), mas oTextBoxChanged
evento é disparado duas vezesfonte
TextInput
faz?" Não estou familiarizado comTextInput
...Isso soa como um bug para mim. Como solução alternativa, você sempre pode usar Rx
DistinctUntilChanged
. Existe uma sobrecarga que permite especificar a chave distinta.Este método de extensão retorna o evento TextChanged observável, mas ignora duplicatas consecutivas:
Assim que o bug for corrigido, você pode simplesmente remover a
DistinctUntilChanged
linha.fonte
Agradável! Eu encontrei essa pergunta procurando por um problema relacionado e também achei essa coisa irritante no meu código. O evento duplo consome mais recursos da CPU no meu caso. Então, eu consertei minha caixa de texto de filtro em tempo real com esta solução:
fonte
Acredito que isso sempre foi um bug no Compact Framework. Deve ter sido transportado para o WP7.
fonte
Claro que parece um bug para mim, se você está tentando acionar um evento toda vez que o texto muda, você pode tentar usar uma ligação bidirecional, infelizmente isso não levantará eventos de mudança por pressionamento de tecla (somente quando o campo perde o foco). Aqui está uma solução alternativa se você precisar de uma:
fonte
textBlock1.Text
mudança - vou tentar. (A solução que eu tentaria era tornar meu manipulador de eventos com estado, lembrando o texto anterior. Se ele não mudou, ignore :)Disclaimer- Não estou familiarizado com nuances xaml e sei que isso soa ilógico ... mas de qualquer maneira- meu primeiro pensamento é tentar passar apenas como eventos simples, em vez de eventos modificados por texto. Não faz sentido, mas pode ajudar? Parece que quando eu vi disparos duplos como este antes que é devido a um bug ou devido a alguma forma de 2 chamadas de manipulador de eventos adicionais acontecendo nos bastidores ... Não tenho certeza de qual?
Se você precisa de algo rápido e sujo, novamente, eu não tendo experiência com xaml - meu próximo passo seria apenas pular o xaml para aquela caixa de texto como uma solução rápida ... faça essa caixa de texto totalmente em c # por enquanto até que você possa localizar o bug ou código complicado ... isto é, se você precisar de uma solução temporária.
fonte
Não acho que seja um bug. Quando você atribui o valor a uma propriedade text dentro do evento textchanged, o valor da caixa de texto é alterado, o que irá chamar novamente o evento text alterado.
tente fazer isso no aplicativo Windows Forms, você pode obter um erro
"Ocorreu uma exceção não tratada do tipo 'System.StackOverflowException' em System.Windows.Forms.dll"
fonte
StefanWick está certo, considere usar este modelo
fonte
É um tópico antigo, mas ao invés de mudar o template (isso não funciona para mim, não vejo a outra caixa de texto com o Blend) você pode adicionar booleano para verificar se o evento já fez a função ou não.
Sei que NÃO é a maneira perfeita, mas acho que é a maneira mais simples de fazer isso. E funciona.
fonte