自定义水印输入框和密码框

一、水印输入框

要自定义水印输入框,就要先对TextBox的Template有些了解,下面是TextBox的Template

<ControlTemplate x:Key="PhoneDisabledTextBoxTemplate" TargetType="TextBox">
     <ContentControl x:Name="ContentElement" BorderThickness="0" HorizontalContentAlignment="Stretch" Margin="{StaticResource PhoneTextBoxInnerMargin}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="Stretch"/>
 </ControlTemplate>
 <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="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>
                     </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>
                 </Grid>
             </ControlTemplate>
         </Setter.Value>
     </Setter>
 </Style>

从上面的Template中分析发现,我们可以修改Name="EnabledBorder"的Border里的布局来实现我们的水印效果。

具体思路是,在<ContentControl x:Name="ContentElement" ......>的后面添加一个一样的ContentControl控件,来显示我们的水印内容,并根据TextBox的Text属性和聚焦状态动态的隐藏和显示我们添加的ContentControl。

实现步骤

(一)、我们先创建一个引用库,创建一个文件夹名字为“Themes”,并在Themes文件夹下创建一个名字为“Generic.xaml”的文件并将文件 Generic.xaml的Build Action 设置为Resource。(注意:名字不可改)    Generic.xaml代码如下:

<ResourceDictionary
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"       
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:local="clr-namespace:WaterTextBox" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     mc:Ignorable="d">
 
     <ControlTemplate x:Key="PhoneDisabledTextBoxTemplate" TargetType="TextBox">
         <ContentControl x:Name="ContentElement" BorderThickness="0" HorizontalContentAlignment="Stretch" Margin="{StaticResource PhoneTextBoxInnerMargin}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="Stretch"/>
     </ControlTemplate>
     <Style TargetType="local:WaterTextBox">
         <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="local:WaterTextBox">
                     <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="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>
                         </VisualStateManager.VisualStateGroups>
                         <Border x:Name="EnabledBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Margin="{StaticResource PhoneTouchTargetOverhang}">
                             <Grid>
                                 <ContentControl x:Name="WaterCoElement" Content="{TemplateBinding WaterContent}" FontStyle="Italic" Foreground="{TemplateBinding WaterForeground}" Margin="{StaticResource PhoneTextBoxInnerMargin}" d:LayoutOverrides="Height" Padding="{TemplateBinding Padding}" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"/>
                                 <ContentControl x:Name="ContentElement" BorderThickness="0" HorizontalContentAlignment="Stretch" Margin="{StaticResource PhoneTextBoxInnerMargin}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="Stretch"/>
                             </Grid>
                         </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>
                     </Grid>
                 </ControlTemplate>
             </Setter.Value>
         </Setter>
     </Style>
     
 </ResourceDictionary>

(二)、创建我们的水印输入框控件类,使其继承TextBox。具体代码如下

using System;
 using System.Net;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Documents;
 using System.Windows.Ink;
 using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Media.Animation;
 using System.Windows.Shapes;
 
 namespace WaterTextBox
 {
     public class WaterTextBox : TextBox
     {
         public static DependencyProperty WaterContentProprty = DependencyProperty.Register("WaterContent", typeof(object), typeof(WaterTextBox), new PropertyMetadata("水印输入框"));
 
         public object WaterContent
         {
             get
             {
                 return GetValue(WaterContentProprty);
             }
 
             set
             {
                 SetValue(WaterContentProprty, value);
             }
         }
 
         public static DependencyProperty WaterForegroundProprty = DependencyProperty.Register("WaterForeground", typeof(Brush), typeof(WaterTextBox), new PropertyMetadata(new SolidColorBrush(Colors.Gray)));
 
         public Brush WaterForeground
         {
             get
             {
                 return (Brush)GetValue(WaterForegroundProprty);
             }
 
             set
             {
                 SetValue(WaterForegroundProprty, value);
             }
         }
 
         public WaterTextBox()
         {
             DefaultStyleKey = typeof(WaterTextBox);
         }
 
         ContentControl WaterContentElement = null;
 
         public override void OnApplyTemplate()
         {
             base.OnApplyTemplate();
             WaterContentElement = this.GetTemplateChild("WaterCoElement") as ContentControl;
             if (WaterContentElement != null)
             {
                 if (string.IsNullOrEmpty(Text))
                     WaterContentElement.Visibility = System.Windows.Visibility.Visible;
                 else
                     WaterContentElement.Visibility = System.Windows.Visibility.Collapsed;
             }
         }
 
         protected override void OnGotFocus(RoutedEventArgs e)
         {
             if (WaterContentElement != null && string.IsNullOrEmpty(Text))
                 WaterContentElement.Visibility = Visibility.Collapsed;
             base.OnGotFocus(e);
         }
 
         protected override void OnLostFocus(RoutedEventArgs e)
         {
             if (WaterContentElement != null && string.IsNullOrEmpty(Text))
                 WaterContentElement.Visibility = Visibility.Visible;
             base.OnLostFocus(e);
         }
     }
 }

此处重载了TextBox的三个函数,分别是OnGotFocus、OnLostFocus和OnApplyTemplate,重载OnApplyTemplate在这里我们可以得到我们下名为WaterCoElement的ContentControl控件,来动态的控制显示隐藏。到这里我们的水印输入框就做好了。(注意:因为我们是使用ContentControl来显示水印的内容,而ContentControl的Content是Object,所以呢,我们可以在里面放任何复杂的控件)下面看下效果:

二、水印密码框

思路:既然水印输入框做好了,密码框和输入框差不多,我们是不是可以一样字画葫芦那?这个想法自然是最容易想到的,但可惜PasswordBox是一个封闭类,不可以继承,⊙﹏⊙b汗。那怎么办?既然TextBox和PasswordBox很相近,我们是不是可以从TextBox下手那。上面水印输入框是修改了Border.Name="EnabledBorder",在Border下面有一个ContentControl,那么我们把ContentControl换成PasswordBox是否可行那?让我们try一下吧。(PS:此处只是我做的时候一个想法,不过得到证实没有问题

步骤同上面水印输入框一样,直接上代码:

<ResourceDictionary
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"       
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:local="clr-namespace:WaterTextBox" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     mc:Ignorable="d">
 
     <ControlTemplate x:Key="PhoneDisabledTextBoxTemplate" TargetType="TextBox">
         <ContentControl x:Name="ContentElement" BorderThickness="0" HorizontalContentAlignment="Stretch" Margin="{StaticResource PhoneTextBoxInnerMargin}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="Stretch"/>
     </ControlTemplate>
     <Style TargetType="local:WaterPasswordBox">
         <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="local:WaterPasswordBox">
                     <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="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>
                         </VisualStateManager.VisualStateGroups>
                         <Border x:Name="EnabledBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Margin="{StaticResource PhoneTouchTargetOverhang}">
                             <Grid>
                                 <ContentControl x:Name="WaterCoElement" Content="{TemplateBinding WaterContent}" FontStyle="Italic" Foreground="{TemplateBinding WaterForeground}" Margin="{StaticResource PhoneTextBoxInnerMargin}" d:LayoutOverrides="Height" Padding="{TemplateBinding Padding}" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"/>
                                 <PasswordBox x:Name="ContentElement" Password="{Binding Text}" Background="{Binding Background}" BorderThickness="0" HorizontalContentAlignment="Stretch" Margin="-12" Padding="{TemplateBinding Padding}" VerticalContentAlignment="Stretch"/>
                             </Grid>
                         </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>
                     </Grid>
                 </ControlTemplate>
             </Setter.Value>
         </Setter>
     </Style>
 
 </ResourceDictionary>

.Cs

using System;
 using System.Net;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Documents;
 using System.Windows.Ink;
 using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Media.Animation;
 using System.Windows.Shapes;
 
 namespace WaterTextBox
 {
     public class WaterPasswordBox : TextBox
     {
         public static DependencyProperty WaterContentProprty = DependencyProperty.Register("WaterContent", typeof(object), typeof(WaterPasswordBox), new PropertyMetadata("水印密码框"));
 
         public object WaterContent
         {
             get
             {
                 return GetValue(WaterContentProprty);
             }
 
             set
             {
                 SetValue(WaterContentProprty, value);
             }
         }
 
         public static DependencyProperty WaterForegroundProprty = DependencyProperty.Register("WaterForeground", typeof(Brush), typeof(WaterPasswordBox), new PropertyMetadata(new SolidColorBrush(Colors.Gray)));
 
         public Brush WaterForeground
         {
             get
             {
                 return (Brush)GetValue(WaterForegroundProprty);
             }
 
             set
             {
                 SetValue(WaterForegroundProprty, value);
             }
         }
 
         public WaterPasswordBox()
         {
             DefaultStyleKey = typeof(WaterPasswordBox);
         }
 
         ContentControl WaterContentElement = null;
         PasswordBox PasswordBoxElement = null;
 
         public override void OnApplyTemplate()
         {
             base.OnApplyTemplate();
             WaterContentElement = this.GetTemplateChild("WaterCoElement") as ContentControl;
             PasswordBoxElement = this.GetTemplateChild("ContentElement") as PasswordBox;
             if (WaterContentElement != null && PasswordBoxElement != null)
             {
                 if (string.IsNullOrEmpty(PasswordBoxElement.Password))
                     WaterContentElement.Visibility = System.Windows.Visibility.Visible;
                 else
                     WaterContentElement.Visibility = System.Windows.Visibility.Collapsed;
             }
         }
 
         protected override void OnGotFocus(RoutedEventArgs e)
         {
             if (WaterContentElement != null && string.IsNullOrEmpty(PasswordBoxElement.Password))
                 WaterContentElement.Visibility = Visibility.Collapsed;
             base.OnGotFocus(e);
         }
 
         protected override void OnLostFocus(RoutedEventArgs e)
         {
             if (WaterContentElement != null && string.IsNullOrEmpty(PasswordBoxElement.Password))
                 WaterContentElement.Visibility = Visibility.Visible;
             base.OnLostFocus(e);
         }
     }
 }

运行效果:

Ok搞定了,使用下还不错,不过PasswordBox的属性在WaterPasswordBox中无法使用。⊙﹏⊙b汗

Ps:如果你想让WaterPasswordBox和PasswordBox一样可以设置很多属性,那就开一些和WaterContent一样的依赖属性,或者你直接开一个Style属性吧。

源码下载:https://files.cnblogs.com/qq278360339/PhoneApp_1.rar

Ps:给大家介绍一个不错我wp论坛,卤面网

原文链接:http://www.cnblogs.com/qq278360339/archive/2012/07/05/2577509.html

原文地址:https://www.cnblogs.com/dacheng/p/2622107.html