首页 > 代码库 > 【WP8】让TextBox文本支持滑动(Scroll)

【WP8】让TextBox文本支持滑动(Scroll)

通过修改样式让TextBox支持文本滑动

  在Silverlight上,TextBox是有文本滚动的功能的,当TextBox的文本过长时,可以进行拖动的,TextBox使用 VerticalScrollBarVisibility 和 HorizontalScrollBarVisibility 来控制滚动条的显示

在Windows Phone上的TextBox 也拥有 VerticalScrollBarVisibility 和 HorizontalScrollBarVisibility 两个属性,但是当设置这两个属性Visible后,却发现TextBox上的文本滑动不了,下面对比Silverlight和WP上的TextBox样式

WP8上的TextBox样式如下:

    <Style x:Key="TextBoxStyle1" TargetType="TextBox">        <Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilyNormal}"/>        <Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMediumLarge}"/>        <Setter Property="Background" Value="{StaticResource PhoneTextBoxBrush}"/>        <Setter Property="Foreground" Value="{StaticResource PhoneTextBoxForegroundBrush}"/>        <Setter Property="BorderBrush" Value="{StaticResource PhoneTextBoxBrush}"/>        <Setter Property="SelectionBackground" Value="{StaticResource PhoneAccentBrush}"/>        <Setter Property="SelectionForeground" Value="{StaticResource PhoneTextBoxSelectionForegroundBrush}"/>        <Setter Property="BorderThickness" Value="{StaticResource PhoneBorderThickness}"/>        <Setter Property="Padding" Value="2"/>        <Setter Property="Template">            <Setter.Value>                <ControlTemplate TargetType="TextBox">                    <Grid Background="Transparent">                        <VisualStateManager.VisualStateGroups>                            <VisualStateGroup x:Name="CommonStates">                                <VisualState x:Name="Normal"/>                                <VisualState x:Name="MouseOver"/>                                <VisualState x:Name="Disabled">                                    <Storyboard>                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="MainBorder">                                            <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>                                        </ObjectAnimationUsingKeyFrames>                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="MainBorder">                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>                                        </ObjectAnimationUsingKeyFrames>                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentElement">                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>                                        </ObjectAnimationUsingKeyFrames>                                    </Storyboard>                                </VisualState>                                <VisualState x:Name="ReadOnly">                                    <Storyboard>                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="MainBorder">                                            <DiscreteObjectKeyFrame KeyTime="0">                                                <DiscreteObjectKeyFrame.Value>                                                    <Visibility>Collapsed</Visibility>                                                </DiscreteObjectKeyFrame.Value>                                            </DiscreteObjectKeyFrame>                                        </ObjectAnimationUsingKeyFrames>                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ReadonlyBorder">                                            <DiscreteObjectKeyFrame KeyTime="0">                                                <DiscreteObjectKeyFrame.Value>                                                    <Visibility>Visible</Visibility>                                                </DiscreteObjectKeyFrame.Value>                                            </DiscreteObjectKeyFrame>                                        </ObjectAnimationUsingKeyFrames>                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ReadonlyBorder">                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxBrush}"/>                                        </ObjectAnimationUsingKeyFrames>                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ReadonlyBorder">                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxBrush}"/>                                        </ObjectAnimationUsingKeyFrames>                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentElement">                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxReadOnlyBrush}"/>                                        </ObjectAnimationUsingKeyFrames>                                    </Storyboard>                                </VisualState>                            </VisualStateGroup>                            <VisualStateGroup x:Name="FocusStates">                                <VisualState x:Name="Focused">                                    <Storyboard>                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="MainBorder">                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxEditBackgroundBrush}"/>                                        </ObjectAnimationUsingKeyFrames>                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="MainBorder">                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxEditBorderBrush}"/>                                        </ObjectAnimationUsingKeyFrames>                                    </Storyboard>                                </VisualState>                                <VisualState x:Name="Unfocused"/>                            </VisualStateGroup>                        </VisualStateManager.VisualStateGroups>                        <Border x:Name="MainBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Margin="{StaticResource PhoneTouchTargetOverhang}"/>                        <Border x:Name="ReadonlyBorder" BorderBrush="{StaticResource PhoneDisabledBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="Transparent" Margin="{StaticResource PhoneTouchTargetOverhang}" Visibility="Collapsed"/>                        <Border BorderBrush="Transparent" BorderThickness="{TemplateBinding BorderThickness}" Background="Transparent" Margin="{StaticResource PhoneTouchTargetOverhang}">                            <ContentControl x:Name="ContentElement" BorderThickness="0" HorizontalContentAlignment="Stretch" Margin="{StaticResource PhoneTextBoxInnerMargin}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="Stretch"/>                        </Border>                    </Grid>                </ControlTemplate>            </Setter.Value>        </Setter>    </Style>
WP8上TextBox默认样式

Silverlight上的TextBox样式如下(Silverlight支持文本滚动)

    <ControlTemplate x:Key="ValidationToolTipTemplate">        <Grid x:Name="Root" Margin="5,0" Opacity="0" RenderTransformOrigin="0,0">            <Grid.RenderTransform>                <TranslateTransform x:Name="xform" X="-25"/>            </Grid.RenderTransform>            <VisualStateManager.VisualStateGroups>                <VisualStateGroup x:Name="OpenStates">                    <VisualStateGroup.Transitions>                        <VisualTransition GeneratedDuration="0"/>                        <VisualTransition GeneratedDuration="0:0:0.2" To="Open">                            <Storyboard>                                <DoubleAnimation Duration="0:0:0.2" To="0" Storyboard.TargetProperty="X" Storyboard.TargetName="xform">                                    <DoubleAnimation.EasingFunction>                                        <BackEase Amplitude=".3" EasingMode="EaseOut"/>                                    </DoubleAnimation.EasingFunction>                                </DoubleAnimation>                                <DoubleAnimation Duration="0:0:0.2" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Root"/>                            </Storyboard>                        </VisualTransition>                    </VisualStateGroup.Transitions>                    <VisualState x:Name="Closed">                        <Storyboard>                            <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Root"/>                        </Storyboard>                    </VisualState>                    <VisualState x:Name="Open">                        <Storyboard>                            <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="X" Storyboard.TargetName="xform"/>                            <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Root"/>                        </Storyboard>                    </VisualState>                </VisualStateGroup>            </VisualStateManager.VisualStateGroups>            <Border Background="#052A2E31" CornerRadius="5" Margin="4,4,-4,-4"/>            <Border Background="#152A2E31" CornerRadius="4" Margin="3,3,-3,-3"/>            <Border Background="#252A2E31" CornerRadius="3" Margin="2,2,-2,-2"/>            <Border Background="#352A2E31" CornerRadius="2" Margin="1,1,-1,-1"/>            <Border Background="#FFDC000C" CornerRadius="2"/>            <Border CornerRadius="2">                <TextBlock Foreground="White" MaxWidth="250" Margin="8,4,8,4" TextWrapping="Wrap" Text="{Binding (Validation.Errors)[0].ErrorContent}" UseLayoutRounding="false"/>            </Border>        </Grid>    </ControlTemplate>    <Style x:Key="TextBoxStyle1" TargetType="TextBox">        <Setter Property="Template">            <Setter.Value>                <ControlTemplate TargetType="TextBox">                    <Grid x:Name="RootElement">                        <VisualStateManager.VisualStateGroups>                            <VisualStateGroup x:Name="CommonStates">                                <VisualState x:Name="Normal"/>                                <VisualState x:Name="MouseOver">                                    <Storyboard>                                        <ColorAnimation Duration="0" To="#FF99C1E2" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" Storyboard.TargetName="MouseOverBorder"/>                                    </Storyboard>                                </VisualState>                                <VisualState x:Name="Disabled">                                    <Storyboard>                                        <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="DisabledVisualElement"/>                                    </Storyboard>                                </VisualState>                                <VisualState x:Name="ReadOnly">                                    <Storyboard>                                        <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ReadOnlyVisualElement"/>                                    </Storyboard>                                </VisualState>                            </VisualStateGroup>                            <VisualStateGroup x:Name="FocusStates">                                <VisualState x:Name="Focused">                                    <Storyboard>                                        <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="FocusVisualElement"/>                                    </Storyboard>                                </VisualState>                                <VisualState x:Name="Unfocused">                                    <Storyboard>                                        <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="FocusVisualElement"/>                                    </Storyboard>                                </VisualState>                            </VisualStateGroup>                            <VisualStateGroup x:Name="ValidationStates">                                <VisualState x:Name="Valid"/>                                <VisualState x:Name="InvalidUnfocused">                                    <Storyboard>                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ValidationErrorElement">                                            <DiscreteObjectKeyFrame KeyTime="0">                                                <DiscreteObjectKeyFrame.Value>                                                    <Visibility>Visible</Visibility>                                                </DiscreteObjectKeyFrame.Value>                                            </DiscreteObjectKeyFrame>                                        </ObjectAnimationUsingKeyFrames>                                    </Storyboard>                                </VisualState>                                <VisualState x:Name="InvalidFocused">                                    <Storyboard>                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ValidationErrorElement">                                            <DiscreteObjectKeyFrame KeyTime="0">                                                <DiscreteObjectKeyFrame.Value>                                                    <Visibility>Visible</Visibility>                                                </DiscreteObjectKeyFrame.Value>                                            </DiscreteObjectKeyFrame>                                        </ObjectAnimationUsingKeyFrames>                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsOpen" Storyboard.TargetName="validationTooltip">                                            <DiscreteObjectKeyFrame KeyTime="0">                                                <DiscreteObjectKeyFrame.Value>                                                    <system:Boolean>True</system:Boolean>                                                </DiscreteObjectKeyFrame.Value>                                            </DiscreteObjectKeyFrame>                                        </ObjectAnimationUsingKeyFrames>                                    </Storyboard>                                </VisualState>                            </VisualStateGroup>                        </VisualStateManager.VisualStateGroups>                        <Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Margin="{StaticResource PhoneTouchTargetOverhang}">                            <Grid>                                <Border x:Name="ReadOnlyVisualElement" Background="#5EC9C9C9" Opacity="0"/>                                <Border x:Name="MouseOverBorder" BorderBrush="Transparent" BorderThickness="1">                                    <ScrollViewer x:Name="ContentElement" BorderThickness="0" IsTabStop="False" Padding="{TemplateBinding Padding}"/>                                </Border>                            </Grid>                        </Border>                        <Border x:Name="DisabledVisualElement" BorderBrush="#A5F7F7F7" BorderThickness="{TemplateBinding BorderThickness}" Background="#A5F7F7F7" IsHitTestVisible="False" Opacity="0"/>                        <Border x:Name="FocusVisualElement" BorderBrush="#FF6DBDD1" BorderThickness="{TemplateBinding BorderThickness}" IsHitTestVisible="False" Margin="1" Opacity="0"/>                        <Border x:Name="ValidationErrorElement" BorderBrush="#FFDB000C" BorderThickness="1" CornerRadius="1" Visibility="Collapsed">                            <ToolTipService.ToolTip>                                <ToolTip x:Name="validationTooltip" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" Placement="Right" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}" Template="{StaticResource ValidationToolTipTemplate}">                                    <ToolTip.Triggers>                                        <EventTrigger RoutedEvent="Canvas.Loaded">                                            <BeginStoryboard>                                                <Storyboard>                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsHitTestVisible" Storyboard.TargetName="validationTooltip">                                                        <DiscreteObjectKeyFrame KeyTime="0">                                                            <DiscreteObjectKeyFrame.Value>                                                                <system:Boolean>true</system:Boolean>                                                            </DiscreteObjectKeyFrame.Value>                                                        </DiscreteObjectKeyFrame>                                                    </ObjectAnimationUsingKeyFrames>                                                </Storyboard>                                            </BeginStoryboard>                                        </EventTrigger>                                    </ToolTip.Triggers>                                </ToolTip>                            </ToolTipService.ToolTip>                            <Grid Background="Transparent" HorizontalAlignment="Right" Height="12" Margin="1,-4,-4,0" VerticalAlignment="Top" Width="12">                                <Path Data="M 1,0 L6,0 A 2,2 90 0 1 8,2 L8,7 z" Fill="#FFDC000C" Margin="1,3,0,0"/>                                <Path Data="M 0,0 L2,0 L 8,6 L8,8" Fill="#ffffff" Margin="1,3,0,0"/>                            </Grid>                        </Border>                    </Grid>                </ControlTemplate>            </Setter.Value>        </Setter>    </Style>
Silverlight上TextBox默认样式

 

通过对比TextBox的样式发现,WP8上的TextBox样式模板里面并没有ScrollViewer控件,而Silverlight中的TextBox是有ScrollViewer的,可以正常滚动,我们把WP8上的TextBox样式中的ContentControl改为ScrollViewer

    <Style x:Key="TextBoxStyle2" TargetType="TextBox">        <Setter Property="Template">            <Setter.Value>                <ControlTemplate TargetType="TextBox">                    <Grid Background="Transparent">                        <VisualStateManager.VisualStateGroups>                            <VisualStateGroup x:Name="CommonStates">                                <VisualState x:Name="Normal"/>                                <VisualState x:Name="MouseOver"/>                                <VisualState x:Name="Disabled">                                    <Storyboard>                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="MainBorder">                                            <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>                                        </ObjectAnimationUsingKeyFrames>                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="MainBorder">                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>                                        </ObjectAnimationUsingKeyFrames>                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentElement">                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>                                        </ObjectAnimationUsingKeyFrames>                                    </Storyboard>                                </VisualState>                                <VisualState x:Name="ReadOnly">                                    <Storyboard>                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="MainBorder">                                            <DiscreteObjectKeyFrame KeyTime="0">                                                <DiscreteObjectKeyFrame.Value>                                                    <Visibility>Collapsed</Visibility>                                                </DiscreteObjectKeyFrame.Value>                                            </DiscreteObjectKeyFrame>                                        </ObjectAnimationUsingKeyFrames>                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ReadonlyBorder">                                            <DiscreteObjectKeyFrame KeyTime="0">                                                <DiscreteObjectKeyFrame.Value>                                                    <Visibility>Visible</Visibility>                                                </DiscreteObjectKeyFrame.Value>                                            </DiscreteObjectKeyFrame>                                        </ObjectAnimationUsingKeyFrames>                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ReadonlyBorder">                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxBrush}"/>                                        </ObjectAnimationUsingKeyFrames>                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ReadonlyBorder">                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxBrush}"/>                                        </ObjectAnimationUsingKeyFrames>                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentElement">                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxReadOnlyBrush}"/>                                        </ObjectAnimationUsingKeyFrames>                                    </Storyboard>                                </VisualState>                            </VisualStateGroup>                            <VisualStateGroup x:Name="FocusStates">                                <VisualState x:Name="Focused">                                    <Storyboard>                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="MainBorder">                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxEditBackgroundBrush}"/>                                        </ObjectAnimationUsingKeyFrames>                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="MainBorder">                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxEditBorderBrush}"/>                                        </ObjectAnimationUsingKeyFrames>                                    </Storyboard>                                </VisualState>                                <VisualState x:Name="Unfocused"/>                            </VisualStateGroup>                        </VisualStateManager.VisualStateGroups>                        <Border x:Name="MainBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Margin="{StaticResource PhoneTouchTargetOverhang}"/>                        <Border x:Name="ReadonlyBorder" BorderBrush="{StaticResource PhoneDisabledBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="Transparent" Margin="{StaticResource PhoneTouchTargetOverhang}" Visibility="Collapsed"/>                        <Border BorderBrush="Transparent" BorderThickness="{TemplateBinding BorderThickness}" Background="Transparent" Margin="{StaticResource PhoneTouchTargetOverhang}">                            <ScrollViewer x:Name="ContentElement" BorderThickness="0" IsTabStop="False" Padding="{TemplateBinding Padding}" Margin="{StaticResource PhoneTextBoxInnerMargin}" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"/>                        </Border>                    </Grid>                </ControlTemplate>            </Setter.Value>        </Setter>    </Style>
WP8的TextBox修改后的样式

测试后发现,WP8上的TextBox可以滑动了(但发现看不到ScrollBar)

 

控制TextBox显示文本的位置

  有时候我们需要在代码中向TextBox的Text添加内容,比如表情,这时候TextBox不在编辑状态,我们添加文本后可以通过TextBox.SelectionStart去控制TextBox显示的位置,添加内容后TextBox.SelectionStart会被设置为0,如果需要显示文本的末尾,可以用 textBox.SelectionStart = textBox.Text.Length - 1;