It's very rare that I ever use the TextChanged
event directly… but never say never!
I recently needed it and for some weird reason, it fired twice for every key pressed. Here is a simplified example of the problem. I added a simple TextBlock
and TextBox
.
<phone:PhoneApplicationPage
x:Class="TextBoxTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True">
<StackPanel>
<TextBlock Text="Count: 0" x:Name="counterTextBlock" />
<TextBox x:Name="textBox" TextChanged="textBox_TextChanged" />
</StackPanel>
</phone:PhoneApplicationPage>
And then attached the TextChanged
event handler from XAML. The event handler just increments a counter and prints it on the screen.
public partial class MainPage : PhoneApplicationPage
{
public MainPage()
{
InitializeComponent();
}
int count = 0;
private void textBox_TextChanged(object sender, TextChangedEventArgs e)
{
count++;
counterTextBlock.Text = "Count: " + count;
}
}
Running it, for every letter I type, it increments twice (sounds weird, but try it).
After searching a bit, I found this post on Stackoverflow (by none other than the legend Jon Skeet) about exactly the same problem. It turns out that the problem is how the TextBox
was styled to Metro-fy™ it… Here is a simplified version of the original template:
<Style x:Key="SimplefiedTextBoxStyle" TargetType="TextBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid Background="Transparent">
<Border x:Name="EnabledBorder">
<ContentControl x:Name="ContentElement" />
</Border>
<Border x:Name="DisabledOrReadonlyBorder"
Visibility="Collapsed">
<TextBox x:Name="DisabledOrReadonlyContent"
Text="{TemplateBinding Text}" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Notice the second TextBox
, if you remove it… the event only fires once (but then you have no differentiation when disabled/read only).