TextBox.TextChanged event firing twice on Windows Phone 7 emulator
Solution 1
The reason the TextChanged
event fires twice in WP7 is a side effect of how the TextBox
has been templated for the Metro look.
If you edit the TextBox
template in Blend you will see that it contains a secondary TextBox
for the disabled/read-only state. This causes, as a side effect, the event to fire twice.
You can change the template to remove the extra TextBox
(and associated states) if you don't need these states, or modify the template to achieve a different look in the disabled/read-only state, without using a secondary TextBox
.
With that, the event will fire only once.
Solution 2
i'd go for the bug, mainly because if you put the KeyDown
and KeyUp
events in there, it shows that that they are fired only once (each of them) but the TextBoxChanged
event is fired twice
Solution 3
That does sound like a bug to me. As a workaround, you could always use Rx's DistinctUntilChanged
. There is an overload that allows you to specify the distinct key.
This extension method returns the observable TextChanged event but skips consecutive duplicates:
public static IObservable<IEvent<TextChangedEventArgs>> GetTextChanged(
this TextBox tb)
{
return Observable.FromEvent<TextChangedEventArgs>(
h => textBox1.TextChanged += h,
h => textBox1.TextChanged -= h
)
.DistinctUntilChanged(t => t.Text);
}
Once the bug is fixed you can simply remove the DistinctUntilChanged
line.
Solution 4
Nice! I found this question by searching for a related problem and also found this annoying thing in my code. Double event eats more CPU resources in my case. So, I fixed my real-time filter textbox with this solution:
private string filterText = String.Empty;
private void SearchBoxUpdated( object sender, TextChangedEventArgs e )
{
if ( filterText != filterTextBox.Text )
{
// one call per change
filterText = filterTextBox.Text;
...
}
}
Solution 5
I believe this has always been a bug in the Compact Framework. It must have been carried over into WP7.
Jon Skeet
Author of C# in Depth. Currently a software engineer at Google, London. Usually a Microsoft MVP (C#, 2003-2010, 2011-) Sites: C# in Depth Coding blog C# articles Twitter updates (@jonskeet) Email: [email protected] (but please read my blog post on Stack Overflow-related emails first)
Updated on June 02, 2022Comments
-
Jon Skeet almost 2 years
I have a very simple test app just to play around with Windows Phone 7. I've just added a
TextBox
and aTextBlock
to the standard UI template. The only custom code is the following: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"; } }
The
TextBox.TextChanged
event is wired up toTextBoxChanged
in the XAML:<TextBox Height="72" HorizontalAlignment="Left" Margin="6,37,0,0" Name="textBox1" Text="" VerticalAlignment="Top" Width="460" TextChanged="TextBoxChanged" />
However, every time I press a key when running in the emulator (either the on-screen keyboard or the physical one, having pressed Pause to enable the latter) it increments the counter twice, displaying two lines in the
TextBlock
. Everything I've tried shows that the event is genuinely firing twice, and I've no idea why. I've verified that it's only being subscribed once - if I unsubscribe in theMainPage
constructor, nothing happens at all (to the text block) when the text changes.I've tried the equivalent code in a regular Silverlight app, and it didn't occur there. I don't have a physical phone to reproduce this with at the moment. I haven't found any record of this being a known problem in the Windows Phone 7.
Can anyone explain what I'm doing wrong, or should I report this as a bug?
EDIT: To reduce the possibility of this being down to having two text controls, I've tried removing the
TextBlock
completely, and changing the TextBoxChanged method to just incrementcounter
. I've then run in the emulator, typed 10 letters and then put a breakpoint on thecounter++;
line (just to get rid of any possibility that breaking into the debugger is causing issues) - and it showscounter
as 20.EDIT: I've now asked in the Windows Phone 7 forum... we'll see what happens.
-
Jon Skeet almost 14 yearsI'm not sure that that will work around it - the problem isn't the event handler firing because of
textBlock1.Text
changing - I'll give it a try though. (The workaround I was going to try was to make my eventhandler stateful, remembering the previous text. If it hasn't actually changed, ignore it :) -
Jon Skeet almost 14 years@undertakeror: Thanks for checking out that bit. I'll ask the same question on the WP7-specific forum and see what the response is...
-
MordechayS almost 14 yearsWhat does TextInput do? These seems like quite a big bug to slip through the unit tests of the WP7, but then it is SL
-
Jon Skeet almost 14 years@Chris S: What do you mean by "What does
TextInput
do?" I'm not familiar withTextInput
... -
Jon Skeet almost 14 yearsI'm not the one passing any event args - I'm implementing an event handler. But I've verified that adding the event handler purely in C# makes no difference... it still gets fired twice.
-
Pimp Juice McJones almost 14 yearsOK, hmmm. Yeah, if it's pure c# then it sounds more like a bug. About by first suggestion- I'm sorry my verbage was horrible, how I should have stated is- I'd try [in your implementation/TextBoxChanged handler method] change the args parameter type to just plain eventargs. Probably won't work... but hey... it was just my first thought.
-
Pimp Juice McJones almost 14 yearsIn other words, it probably won't work but I'd try method signature = private void TextBoxChanged(object sender, EventArgs e) just to say that I tried it =)
-
MordechayS almost 14 years@Jon ` OnTextInput(TextCompositionEventArgs e)` is the SL way of handling text input instead of KeyDown, as obviously the device may not have a keyboard: "Occurs when a UI element gets text in a device-independent manner" msdn.microsoft.com/en-us/library/…
-
MordechayS almost 14 yearsI was just curious if that fired twice as well
-
Jon Skeet almost 14 yearsRight. I don't think that will have any effective, I'm afraid.
-
Jon Skeet over 13 years@Chris: I'll give it a try if I have time :)
-
Jon Skeet over 13 yearsI thought it was fixed in a more recent version of the CF... and it would be weird to get in despite the move to Silverlight. On the other hand, it's a pretty weird bug to see anyway...
-
Jerod Houghtelling over 13 yearsI agree that it is strange. I reran into it yesterday in a CF 2.0 application.
-
Jon Skeet over 13 yearsFrom the question: "I've just added a TextBox and a TextBlock to the standard UI template" - they're not the same thing. I've got one TextBox which the user can type into, and one TextBlock which displays the count.