Windows Phone 8文本框中的占位符

时间:2014-01-24 04:55:58

标签: c# xaml windows-phone-8

我需要在我的一个文本框中添加占位符,我通过在文本框中包含不透明度较低的文本和占位符文本来完成它,然后在文本框的焦点上删除占位符文本的内容并增加不透明度到1。 我在这里有一个问题,如果用户没有在该字段中输入任何内容并提交输入,则不会触发onfocus事件,因此占位符文本将作为文本框的值发送。如何解决此问题?

2 个答案:

答案 0 :(得分:3)

如果您不想使用图像水印,请查看以下解决方案。

Windows Phone 7 Silverlight Watermark TextBox Control

Windows Phone Watermark TextBox Control

由于仅链接答案在SO中无效,我发布了第二个链接的代码,因为我已经使用过了。

WatermarkTextBox.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;

namespace System.Windows.Controls
{
    [StyleTypedProperty(Property = "WatermarkTextStyle", StyleTargetType = typeof(TextBlock)),
    TemplatePart(Name = "WatermarkText", Type = typeof(TextBlock)),
    TemplateVisualState(Name = "WatermarkTextVisible", GroupName = "WatermarkTextStates"),
    TemplateVisualState(Name = "WatermarkTextHidden", GroupName = "WatermarkTextStates")]
    public class WatermarkTextBox : TextBox
    {

        public static readonly DependencyProperty WatermarkTextProperty = DependencyProperty.Register(
            "WatermarkText",
            typeof(string),
            typeof(WatermarkTextBox),
            new PropertyMetadata("", OnWatermarkTextPropertyChanged));

        public static readonly DependencyProperty WatermarkTextForegroundProperty = DependencyProperty.Register(
            "WatermarkTextForeground",
            typeof(Brush),
            typeof(WatermarkTextBox),
            new PropertyMetadata(new SolidColorBrush(Colors.Gray), OnWatermarkTextForegroundPropertyChanged));

        public static readonly DependencyProperty WatermarkTextStyleProperty = DependencyProperty.Register(
            "WatermarkTextStyle",
            typeof(Style),
            typeof(WatermarkTextBox),
            new PropertyMetadata(null, OnWatermarkTextStylePropertyChanged));



        private bool itsIsFocused = false;

        public string WatermarkText
        {
            get { return (string)this.GetValue(WatermarkTextProperty); }
            set { this.SetValue(WatermarkTextProperty, value); }
        }

        public Brush WatermarkTextForeground
        {
            get { return (Brush)this.GetValue(WatermarkTextForegroundProperty); }
            set { this.SetValue(WatermarkTextForegroundProperty, value); }
        }

        public Style WatermarkTextStyle
        {
            get { return (Style)this.GetValue(WatermarkTextStyleProperty); }
            set { this.SetValue(WatermarkTextStyleProperty, value); }
        }



        private static void OnWatermarkTextPropertyChanged(DependencyObject theTarget, DependencyPropertyChangedEventArgs theDependencyPropertyChangedEventArgs)
        {
            // Do nothing
        }

        private static void OnWatermarkTextForegroundPropertyChanged(DependencyObject theTarget, DependencyPropertyChangedEventArgs theDependencyPropertyChangedEventArgs)
        {
            // Do nothing
        }

        private static void OnWatermarkTextStylePropertyChanged(DependencyObject theTarget, DependencyPropertyChangedEventArgs theDependencyPropertyChangedEventArgs)
        {
            // Do nothing
        }



        public WatermarkTextBox()
            : base()
        {
            this.DefaultStyleKey = typeof(WatermarkTextBox);

            this.GotFocus += new RoutedEventHandler(WatermarkTextBox_GotFocus);
            this.LostFocus += new RoutedEventHandler(WatermarkTextBox_LostFocus);
            this.Loaded += new RoutedEventHandler(WatermarkTextBox_Loaded);
            this.TextChanged += new TextChangedEventHandler(WatermarkTextBox_TextChanged);
        }

        private void WatermarkTextBox_Loaded(object sender, RoutedEventArgs e)
        {
            this.GoToVisualState(true);
        }

        private void WatermarkTextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            this.itsIsFocused = true;
            this.GoToVisualState(false);
        }

        private void WatermarkTextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            this.itsIsFocused = false;
            this.GoToVisualState(true);
        }

        private void WatermarkTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (!this.itsIsFocused)
            {
                this.GoToVisualState(false);
            }
        }

        private void GoToVisualState(bool theIsWatermarkDisplayed)
        {
            if (theIsWatermarkDisplayed && (this.Text == null || (this.Text != null && this.Text.Length == 0)))
            {
                VisualStateManager.GoToState(this, "WatermarkTextVisible", true);
            }
            else
            {
                VisualStateManager.GoToState(this, "WatermarkTextHidden", true);
            }
        }
    }
}

在资源字典中添加样式。

xmlns:controls="clr-namespace:System.Windows.Controls;assembly=YOUR_PROJECT_ASSEMBLY_NAME"

中添加<App />
<Style TargetType="controls:WatermarkTextBox">
    <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="WatermarkTextForeground" Value="#FF868686" />
    <Setter Property="WatermarkTextStyle">
        <Setter.Value>
            <Style TargetType="TextBlock">
                <Setter Property="HorizontalAlignment" Value="Left" />
                <Setter Property="VerticalAlignment" Value="Center" />
                <Setter Property="Margin" Value="20,0,0,0" />
                <Setter Property="TextWrapping" Value="NoWrap" />
            </Style>
        </Setter.Value>
    </Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="controls:WatermarkTextBox">
                <Grid Background="Transparent">
                    <Grid.Resources>
                        <ControlTemplate x:Key="PhoneDisabledTextBoxTemplate" TargetType="controls:WatermarkTextBox">
                            <ContentControl x:Name="ContentElement" BorderThickness="0" HorizontalContentAlignment="Stretch" Margin="{StaticResource PhoneTextBoxInnerMargin}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="Stretch"/>
                        </ControlTemplate>
                    </Grid.Resources>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal"/>
                            <VisualState x:Name="MouseOver"/>
                            <VisualState x:Name="Disabled">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="EnabledBorder">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <Visibility>Collapsed</Visibility>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="DisabledOrReadonlyBorder">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <Visibility>Visible</Visibility>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="ReadOnly">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="EnabledBorder">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <Visibility>Collapsed</Visibility>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="DisabledOrReadonlyBorder">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <Visibility>Visible</Visibility>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="DisabledOrReadonlyBorder">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="DisabledOrReadonlyBorder">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="DisabledOrReadonlyContent">
                                        <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="EnabledBorder">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxEditBackgroundBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="EnabledBorder">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxEditBorderBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Unfocused"/>
                        </VisualStateGroup>
                        <VisualStateGroup x:Name="WatermarkTextStates">
                            <VisualState x:Name="WatermarkTextVisible">
                                <Storyboard>
                                    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="WatermarkTextBlock" Storyboard.TargetProperty="(UIElement.Opacity)">
                                        <EasingDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
                                    </DoubleAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="WatermarkTextHidden">
                                <Storyboard>
                                    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="WatermarkTextBlock" Storyboard.TargetProperty="(UIElement.Opacity)">
                                        <EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
                                    </DoubleAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Border x:Name="EnabledBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Margin="{StaticResource PhoneTouchTargetOverhang}">
                        <ContentControl x:Name="ContentElement" BorderThickness="0" HorizontalContentAlignment="Stretch" Margin="{StaticResource PhoneTextBoxInnerMargin}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="Stretch"/>
                    </Border>
                    <Border x:Name="DisabledOrReadonlyBorder" BorderBrush="{StaticResource PhoneDisabledBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="Transparent" Margin="{StaticResource PhoneTouchTargetOverhang}" Visibility="Collapsed">
                        <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}"/>
                    </Border>
                    <TextBlock x:Name="WatermarkTextBlock" Style="{TemplateBinding WatermarkTextStyle}" Foreground="{TemplateBinding WatermarkTextForeground}" Text="{TemplateBinding WatermarkText}" IsHitTestVisible="False" Grid.ColumnSpan="2" />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

用法:

<phone:PhoneApplicationPage 
    xmlns:controls="clr-namespace:System.Windows.Controls"
    .....>

<controls:WatermarkTextBox WatermarkText="Your Watermark Text" />

答案 1 :(得分:2)

您似乎正在寻找水印文本框。您可以使用在文本框中显示文本的图像。这样,你就不会搞乱文本框的数据绑定。在此处阅读更多内容:http://msdn.microsoft.com/en-us/library/bb613590(v=vs.110).aspx

我将很快通过一个较旧的WP项目中的示例更新我的帖子。

编辑:

这是我使用的代码:

    // location is a textbox
    private void location_TextChanged(object sender, TextChangedEventArgs e)
    {
        if (location.Text == "")
        { 
            ImageBrush watermark = new ImageBrush();
            watermark.ImageSource = 
                new BitmapImage(new Uri(@"/Assets/Misc/watermark.png", UriKind.Relative));
            watermark.AlignmentX = AlignmentX.Left;
            watermark.Stretch = Stretch.None;
            watermark.Opacity = .75;
            location.Background = watermark;
        }
        else
        {
            location.Background = new SolidColorBrush(Colors.White);
        }
    }

    private void location_LostFocus(object sender, RoutedEventArgs e)
    {
        location.Background.Opacity = .75;
    }

这是(有点多余的)文本框XAML:

<TextBox x:Name="location" TextChanged="location_TextChanged" LostFocus="location_LostFocus">
    <TextBox.Background>
        <ImageBrush ImageSource="/Assets/Misc/watermark.png"
                    AlignmentX="Left" Stretch="None"
                    Opacity=".75"/>
    </TextBox.Background>
</TextBox>

水印图像如下所示: enter image description here

需要进行大量调整才能使图像正确,因为您必须考虑适当的背景颜色,字体大小等。

也许有更好的方法可以做到这一点,但我认为这是一个很好的起点。

<强>更新

使用Windows Phone 8.1,您只需使用TextBox的PlaceholderText属性

即可
<TextBox PlaceholderText="Enter search query"/>