Skip to main content.

公告

搜索

最新评论

windows phone中TextBox的诡异事件TextChanged

在做项目时经常会遇到一些问题,但在解决问题后没有来得及总结或记录,慢慢的就遗忘了。每当此时总是觉得有一丝丝遗憾,今天回想起一件过去的问题,随即提键记录。

开门见山,问题是这样的,向TextBox中每输入一个字符TextChanged事件会激发两次,通过单步调试发现的确是执行了两次。Why?

如图:

代码如下

前台XAML和后台 C#:

<phone:PhoneApplicationPage 
    x:Class="TextBoxDemo1.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">

    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!--TitlePanel contains the name of the application and page title-->
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="PageTitle" Text="TextBoxDemo" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>

        <!--ContentPanel - place additional content here-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <StackPanel>
                <TextBox Name="textBox1" Height="72" Width="460" TextChanged="textBox1_TextChanged"/>
                <TextBlock Name="textBlock1" />
            </StackPanel>
        </Grid>
    </Grid>

</phone:PhoneApplicationPage>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;

namespace TextBoxDemo1
{
    public partial class MainPage : PhoneApplicationPage
    {
        // Constructor
        public MainPage()
        {
            InitializeComponent();
        }
        private int counter = 0;
        private void textBox1_TextChanged(object sender, TextChangedEventArgs e)
        {
            textBlock1.Text += "文本改变次数:" + (++counter) + "\r\n";
        }
    }
}

为什么会这样呢?通过网络搜索找到了一张网页http://stackoverflow.com/questions/3438806/textbox-textchanged-event-firing-twice-on-windows-phone-7-emulator

大致意思是TextBox的默认模板的问题,可以通过自定义模板来解决。按照该文的提示,我用Blend打开刚才的项目,并获得默认模板。如图:

取得默认模板后的XAML代码如下:

  1 <phone:PhoneApplicationPage 
  2 x:Class="TextBoxDemo1.MainPage"
  3     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  4     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  5     xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
  6     xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
  7     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  8     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  9     mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
 10     FontFamily="{StaticResource PhoneFontFamilyNormal}"
 11     FontSize="{StaticResource PhoneFontSizeNormal}"
 12     Foreground="{StaticResource PhoneForegroundBrush}"
 13     SupportedOrientations="Portrait" Orientation="Portrait"
 14     shell:SystemTray.IsVisible="True">
 15     <phone:PhoneApplicationPage.Resources>
 16         <ControlTemplate x:Key="PhoneDisabledTextBoxTemplate" TargetType="TextBox">
 17             <ContentControl x:Name="ContentElement" BorderThickness="0" HorizontalContentAlignment="Stretch" Margin="{StaticResource PhoneTextBoxInnerMargin}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="Stretch"/>
 18         </ControlTemplate>
 19         <Style x:Key="TextBoxStyle1" TargetType="TextBox">
 20             <Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilyNormal}"/>
 21             <Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMediumLarge}"/>
 22             <Setter Property="Background" Value="{StaticResource PhoneTextBoxBrush}"/>
 23             <Setter Property="Foreground" Value="{StaticResource PhoneTextBoxForegroundBrush}"/>
 24             <Setter Property="BorderBrush" Value="{StaticResource PhoneTextBoxBrush}"/>
 25             <Setter Property="SelectionBackground" Value="{StaticResource PhoneAccentBrush}"/>
 26             <Setter Property="SelectionForeground" Value="{StaticResource PhoneTextBoxSelectionForegroundBrush}"/>
 27             <Setter Property="BorderThickness" Value="{StaticResource PhoneBorderThickness}"/>
 28             <Setter Property="Padding" Value="2"/>
 29             <Setter Property="Template">
 30                 <Setter.Value>
 31                     <ControlTemplate TargetType="TextBox">
 32                         <Grid Background="Transparent">
 33                             <VisualStateManager.VisualStateGroups>
 34                                 <VisualStateGroup x:Name="CommonStates">
 35                                     <VisualState x:Name="Normal"/>
 36                                     <VisualState x:Name="MouseOver"/>
 37                                     <VisualState x:Name="Disabled">
 38                                         <Storyboard>
 39                                             <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="EnabledBorder">
 40                                                 <DiscreteObjectKeyFrame KeyTime="0">
 41                                                     <DiscreteObjectKeyFrame.Value>
 42                                                         <Visibility>Collapsed</Visibility>
 43                                                     </DiscreteObjectKeyFrame.Value>
 44                                                 </DiscreteObjectKeyFrame>
 45                                             </ObjectAnimationUsingKeyFrames>
 46                                             <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="DisabledOrReadonlyBorder">
 47                                                 <DiscreteObjectKeyFrame KeyTime="0">
 48                                                     <DiscreteObjectKeyFrame.Value>
 49                                                         <Visibility>Visible</Visibility>
 50                                                     </DiscreteObjectKeyFrame.Value>
 51                                                 </DiscreteObjectKeyFrame>
 52                                             </ObjectAnimationUsingKeyFrames>
 53                                         </Storyboard>
 54                                     </VisualState>
 55                                     <VisualState x:Name="ReadOnly">
 56                                         <Storyboard>
 57                                             <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="EnabledBorder">
 58                                                 <DiscreteObjectKeyFrame KeyTime="0">
 59                                                     <DiscreteObjectKeyFrame.Value>
 60                                                         <Visibility>Collapsed</Visibility>
 61                                                     </DiscreteObjectKeyFrame.Value>
 62                                                 </DiscreteObjectKeyFrame>
 63                                             </ObjectAnimationUsingKeyFrames>
 64                                             <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="DisabledOrReadonlyBorder">
 65                                                 <DiscreteObjectKeyFrame KeyTime="0">
 66                                                     <DiscreteObjectKeyFrame.Value>
 67                                                         <Visibility>Visible</Visibility>
 68                                                     </DiscreteObjectKeyFrame.Value>
 69                                                 </DiscreteObjectKeyFrame>
 70                                             </ObjectAnimationUsingKeyFrames>
 71                                             <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="DisabledOrReadonlyBorder">
 72                                                 <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxBrush}"/>
 73                                             </ObjectAnimationUsingKeyFrames>
 74                                             <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="DisabledOrReadonlyBorder">
 75                                                 <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxBrush}"/>
 76                                             </ObjectAnimationUsingKeyFrames>
 77                                             <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="DisabledOrReadonlyContent">
 78                                                 <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxReadOnlyBrush}"/>
 79                                             </ObjectAnimationUsingKeyFrames>
 80                                         </Storyboard>
 81                                     </VisualState>
 82                                 </VisualStateGroup>
 83                                 <VisualStateGroup x:Name="FocusStates">
 84                                     <VisualState x:Name="Focused">
 85                                         <Storyboard>
 86                                             <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="EnabledBorder">
 87                                                 <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxEditBackgroundBrush}"/>
 88                                             </ObjectAnimationUsingKeyFrames>
 89                                             <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="EnabledBorder">
 90                                                 <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxEditBorderBrush}"/>
 91                                             </ObjectAnimationUsingKeyFrames>
 92                                         </Storyboard>
 93                                     </VisualState>
 94                                     <VisualState x:Name="Unfocused"/>
 95                                 </VisualStateGroup>
 96                             </VisualStateManager.VisualStateGroups>
 97                             <Border x:Name="EnabledBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Margin="{StaticResource PhoneTouchTargetOverhang}">
 98                                 <ContentControl x:Name="ContentElement" BorderThickness="0" HorizontalContentAlignment="Stretch" Margin="{StaticResource PhoneTextBoxInnerMargin}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="Stretch"/>
 99                             </Border>
100                             <Border x:Name="DisabledOrReadonlyBorder" BorderBrush="{StaticResource PhoneDisabledBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="Transparent" Margin="{StaticResource PhoneTouchTargetOverhang}" Visibility="Collapsed">
101                                 <TextBox x:Name="DisabledOrReadonlyContent" Background="Transparent" Foreground="{StaticResource PhoneDisabledBrush}" FontWeight="{TemplateBinding FontWeight}" FontStyle="{TemplateBinding FontStyle}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" IsReadOnly="True" SelectionForeground="{TemplateBinding SelectionForeground}" SelectionBackground="{TemplateBinding SelectionBackground}" TextAlignment="{TemplateBinding TextAlignment}" TextWrapping="{TemplateBinding TextWrapping}" Text="{TemplateBinding Text}" Template="{StaticResource PhoneDisabledTextBoxTemplate}"/>
102                             </Border>
103                         </Grid>
104                     </ControlTemplate>
105                 </Setter.Value>
106             </Setter>
107         </Style>
108     </phone:PhoneApplicationPage.Resources>
109 
110     <!--LayoutRoot is the root grid where all page content is placed-->
111     <Grid x:Name="LayoutRoot" Background="Transparent">
112         <Grid.RowDefinitions>
113             <RowDefinition Height="Auto"/>
114             <RowDefinition Height="*"/>
115         </Grid.RowDefinitions>
116 
117         <!--TitlePanel contains the name of the application and page title-->
118         <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
119             <TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
120             <TextBlock x:Name="PageTitle" Text="TextBoxDemo" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
121         </StackPanel>
122 
123         <!--ContentPanel - place additional content here-->
124         <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
125             <StackPanel>
126                 <TextBox Name="textBox1" Height="72" Width="460" TextChanged="textBox1_TextChanged" Style="{StaticResource TextBoxStyle1}"/>
127                 <TextBlock Name="textBlock1" />
128             </StackPanel>
129         </Grid>
130     </Grid>
131 
132 </phone:PhoneApplicationPage>
问题找到了,在第101行,发现里面又嵌套了一个TextBox。最简单的办法就是将第100到102行注释掉,先试试:

果然可以,不过如果你需要将textBox1的IsEnabled设置成False或将IsReadOnly设置成True将出错,这就需要你按需修改上面的模板了。

原文:http://www.cnblogs.com/chengyujia/archive/2012/01/16/2324022.html

Feedback

你还可以输入600/600个字符 发表评论
称呼: (必填) 登录 | 开通博客
邮箱: (选填) 你的邮箱地址不会被公开
网站: (选填)
验证码: (必填)