简体   繁体   中英

Placeholder in windows phone 8 textbox

我需要在我的一个文本框中放置一个占位符,通过在文本框中包含一个不透明度较低的文本和一个占位符文本来实现此目的,然后重点关注文本框,删除占位符文本的内容并将不透明度提高到1。我这里有一个问题,如果用户未在该字段中输入任何内容并提交回车,则不会触发onfocus事件,因此将占位符文本作为文本框的值发送。如何解决此问题?

If you don't want to go with image watermark check out below given solutions.

Windows Phone 7 Silverlight Watermark TextBox Control

Windows Phone Watermark TextBox Control

Since link only answers are not valid in SO, I am posting code for 2nd link because I've used that.

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);
            }
        }
    }
}

Add style in resource dictionary.

Add xmlns:controls="clr-namespace:System.Windows.Controls;assembly=YOUR_PROJECT_ASSEMBLY_NAME" in <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>

Usage:

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

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

It seems that you're looking for a watermark textbox. You can use an image that displays text in your textbox. That way, you won't be messing with the textbox's data-binding. Read more here: http://msdn.microsoft.com/en-us/library/bb613590(v=vs.110).aspx

I'll update my post soon with an example from one of my older WP projects.

Edit:

Here's the code I used:

    // 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;
    }

And here's the (somewhat redundant) textbox 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>

And the watermark image looks like this: 在此处输入图片说明

It took a lot of tweaking to get the image right because you have to consider the appropriate background color, font size, etc.

Perhaps there are better ways of doing this, but I think it's a good starting point.

UPDATE

With Windows Phone 8.1, you can simply use the TextBox's PlaceholderText property

<TextBox PlaceholderText="Enter search query"/>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM