在博客园里看到了好多关于文本框和密码框水印效果的文章,今天有空也来实现一把,最终效果图如下:
文本框的话,稍微好一点直接可以绑定它的Text属性,因为他是个依赖属性,我用了二种方式来实现水印效果:触发器和数据绑定的形式;
一、触发器方式:
<!--触发器的形式进行水印效果--> <Style x:Key="TxbTrigger" TargetType="TextBox" BasedOn="{StaticResource TxbBase}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="TextBox"> <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True"> <Grid> <ScrollViewer x:Name="PART_ContentHost" Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/> <TextBlock x:Name="WaterMark" Focusable="False" Visibility="Collapsed" Text="{TemplateBinding Tag}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Opacity="0.5"/> </Grid> </Border> <ControlTemplate.Triggers> <Trigger Property="IsEnabled" Value="False"> <Setter Property="Opacity" TargetName="border" Value="0.56"/> </Trigger> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="BorderBrush" TargetName="border" Value="#FF7EB4EA"/> </Trigger> <Trigger Property="IsKeyboardFocused" Value="True"> <Setter Property="BorderBrush" TargetName="border" Value="#FF569DE5"/> </Trigger> <Trigger Property="Text" Value=""> <Setter Property="Visibility" TargetName="WaterMark" Value="Visible"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
二、数据绑定方式
<!--绑定和转换器的形式进行水印效果--> <Style x:Key="TxbBing" TargetType="TextBox" BasedOn="{StaticResource TxbBase}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="TextBox"> <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True"> <Grid> <ScrollViewer x:Name="PART_ContentHost" Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/> <TextBlock x:Name="WaterMark" Focusable="False" Visibility="{TemplateBinding Text,Converter={StaticResource TextToVisibility}}" Text="{TemplateBinding Tag}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Opacity="0.5"/> </Grid> </Border> <ControlTemplate.Triggers> <Trigger Property="IsEnabled" Value="False"> <Setter Property="Opacity" TargetName="border" Value="0.56"/> </Trigger> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="BorderBrush" TargetName="border" Value="#FF7EB4EA"/> </Trigger> <Trigger Property="IsKeyboardFocused" Value="True"> <Setter Property="BorderBrush" TargetName="border" Value="#FF569DE5"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
密码框的水印效果就稍微麻烦一点了,因为这个Password它不是依赖属性,所以不能像TextBox的Text进行绑定操作;我这边是通过附加属性的形式进行实现;
代码如下:
/// <summary> /// PasswordBox添加水印辅助类 /// </summary> public class PasswordBoxWaterMark : DependencyObject { public static bool GetIsMonitoring(DependencyObject obj) { return (bool)obj.GetValue(IsMonitoringProperty); } public static void SetIsMonitoring(DependencyObject obj, bool value) { obj.SetValue(IsMonitoringProperty, value); } public static readonly DependencyProperty IsMonitoringProperty = DependencyProperty.RegisterAttached("IsMonitoring", typeof(bool), typeof(PasswordBoxWaterMark), new UIPropertyMetadata(false, OnIsMonitoringChanged)); public static int GetPasswordLength(DependencyObject obj) { return (int)obj.GetValue(PasswordLengthProperty); } public static void SetPasswordLength(DependencyObject obj, int value) { obj.SetValue(PasswordLengthProperty, value); } public static readonly DependencyProperty PasswordLengthProperty = DependencyProperty.RegisterAttached("PasswordLength", typeof(int), typeof(PasswordBoxWaterMark), new UIPropertyMetadata(0)); private static void OnIsMonitoringChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var pb = d as PasswordBox; if (pb == null) { return; } if ((bool)e.NewValue) { pb.PasswordChanged += PasswordChanged; } else { pb.PasswordChanged -= PasswordChanged; } } private static void PasswordChanged(object sender, RoutedEventArgs e) { var pb = sender as PasswordBox; if (pb == null) { return; } SetPasswordLength(pb, pb.Password.Length); } }
PasswordBox的样式如下:
<Style TargetType="PasswordBox"> <Setter Property="Foreground" Value="Red"/> <Setter Property="FontSize" Value="20"/> <!--光标的颜色--> <Setter Property="CaretBrush" Value="Green"/> <Setter Property="Core:PasswordBoxWaterMark.IsMonitoring" Value="true"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type PasswordBox}"> <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True"> <Grid> <ScrollViewer x:Name="PART_ContentHost" Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/> <TextBlock x:Name="WaterMark" Focusable="False" Visibility="Collapsed" Text="{TemplateBinding Tag}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Opacity="0.5"/> </Grid> </Border> <ControlTemplate.Triggers> <Trigger Property="Core:PasswordBoxWaterMark.PasswordLength" Value="0"> <Setter TargetName="WaterMark" Property="Visibility" Value="Visible"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
源码如下:Demo.Zip
时间: 2024-10-26 14:02:08