主题:开发带有水印的文本框控件。水印格式可以自定义。
如图:
1. 在原来的TextBox中,添加并注册一个依赖属性:Watermark,用于前台自定义水印。
2. 在原来的TextBox样式,添加一个用于呈现水印的内容控件:ContentPresenter,并且将Content绑定Watermark。
3. 给整体控件添加GetFocus,LostFocus事件。以便,在获得焦点时,消失水印。失去焦点时,显示水印。
1.新建一个项目:WatermarkerTextBoxControl
2.右击项目,添加新建项,选择模板式控件,并命名为WatermarkerTextBox.cs
3.将下面代码拷入该模板控件里面:
1 public sealed class WatermarkTextBox : TextBox 2 { 3 public static DependencyProperty WatermarkProperty = DependencyProperty.Register("Watermark", typeof(object), typeof(WatermarkTextBox), new PropertyMetadata(null)); 4 public object Watermark 5 { 6 get { return (object)GetValue(WatermarkProperty); } 7 set { SetValue(WatermarkProperty, value); } 8 } 9 public static DependencyProperty WatermarkTemplateProperty = DependencyProperty.Register("WatermarkTemplate", typeof(DataTemplate), typeof(WatermarkTextBox), new PropertyMetadata(null)); 10 public DataTemplate WatermarkTemplate 11 { 12 get { return (DataTemplate)GetValue(WatermarkTemplateProperty); } 13 set { SetValue(WatermarkTemplateProperty, value); } 14 } 15 16 public WatermarkTextBox() 17 { 18 this.DefaultStyleKey = typeof(WatermarkTextBox); 19 this.DefaultStyleKey = typeof(WatermarkTextBox); 20 this.GotFocus += WatermarkTextBox_GotFocus; 21 this.LostFocus += WatermarkTextBox_LostFocus; 22 } 23 void WatermarkTextBox_GotFocus(object sender, RoutedEventArgs e) 24 { 25 GoToWatermarkVisualState(); 26 } 27 28 void WatermarkTextBox_LostFocus(object sender, RoutedEventArgs e) 29 { 30 GoToWatermarkVisualState(false); 31 } 32 33 private void GoToWatermarkVisualState(bool hasFocus = true) 34 { 35 //如果文本框内容为空 或者 没有获得焦点时,显示水印 36 //否则,就隐藏水印 37 if (String.IsNullOrEmpty(Text) && !hasFocus) 38 GoToVisualState("WatermarkVisible"); //TODO: create constants for our magic strings 39 else 40 GoToVisualState("WatermarkCollapsed"); 41 } 42 43 private void GoToVisualState(string stateName, bool useTransitions = true) 44 { 45 //控制水印状态 46 VisualStateManager.GoToState(this, stateName, useTransitions); 47 } 48 49 protected override void OnApplyTemplate() 50 { 51 base.OnApplyTemplate(); 52 53 //we need to set the initial state of the watermark 54 GoToWatermarkVisualState(false); 55 } 56 57 }
代码讲解:
1). 给该控件注册,两个依赖属性,并且添加相应的属性索引器。但是有用的只是:Watermark属性。
2). 在控件构造函数中,添加GetFocus和LostFocus事件,并在事件中添加水印显示与否代码。
3). 水印的控制VisualState会写在该控件的样式中
1. 打开Theme文件夹下的Generic.xaml文件:
2. 将下面的样式代码替换原来的WatermarkTextBox样式:
1 <Style TargetType="local:WatermarkTextBox"> 2 <Setter Property="MinWidth" Value="{StaticResource TextControlThemeMinWidth}"/> 3 <Setter Property="MinHeight" Value="{StaticResource TextControlThemeMinHeight}"/> 4 <Setter Property="Foreground" Value="{StaticResource TextBoxForegroundThemeBrush}"/> 5 <Setter Property="Background" Value="{StaticResource TextBoxBackgroundThemeBrush}"/> 6 <Setter Property="BorderBrush" Value="{StaticResource TextBoxBorderThemeBrush}"/> 7 <Setter Property="BorderThickness" Value="{StaticResource TextControlBorderThemeThickness}"/> 8 <Setter Property="FontFamily" Value="{StaticResource ContentControlThemeFontFamily}"/> 9 <Setter Property="FontSize" Value="{StaticResource ControlContentThemeFontSize}"/> 10 <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden"/> 11 <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden"/> 12 <Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False"/> 13 <Setter Property="Padding" Value="{StaticResource TextControlThemePadding}"/> 14 <Setter Property="Template"> 15 <Setter.Value> 16 <ControlTemplate TargetType="local:WatermarkTextBox"> 17 <Grid> 18 <Grid.Resources> 19 <Style x:Name="DeleteButtonStyle" TargetType="Button"> 20 <Setter Property="Template"> 21 <Setter.Value> 22 <ControlTemplate TargetType="Button"> 23 <Grid> 24 <VisualStateManager.VisualStateGroups> 25 <VisualStateGroup x:Name="CommonStates"> 26 <VisualState x:Name="Normal"/> 27 <VisualState x:Name="PointerOver"> 28 <Storyboard> 29 <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="BackgroundElement"> 30 <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TextBoxButtonPointerOverBackgroundThemeBrush}"/> 31 </ObjectAnimationUsingKeyFrames> 32 <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="BorderElement"> 33 <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TextBoxButtonPointerOverBorderThemeBrush}"/> 34 </ObjectAnimationUsingKeyFrames> 35 <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="GlyphElement"> 36 <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TextBoxButtonPointerOverForegroundThemeBrush}"/> 37 </ObjectAnimationUsingKeyFrames> 38 </Storyboard> 39 </VisualState> 40 <VisualState x:Name="Pressed"> 41 <Storyboard> 42 <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="BackgroundElement"> 43 <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TextBoxButtonPressedBackgroundThemeBrush}"/> 44 </ObjectAnimationUsingKeyFrames> 45 <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="BorderElement"> 46 <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TextBoxButtonPressedBorderThemeBrush}"/> 47 </ObjectAnimationUsingKeyFrames> 48 <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="GlyphElement"> 49 <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TextBoxButtonPressedForegroundThemeBrush}"/> 50 </ObjectAnimationUsingKeyFrames> 51 </Storyboard> 52 </VisualState> 53 <VisualState x:Name="Disabled"> 54 <Storyboard> 55 <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BackgroundElement"/> 56 <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BorderElement"/> 57 </Storyboard> 58 </VisualState> 59 </VisualStateGroup> 60 </VisualStateManager.VisualStateGroups> 61 <Border x:Name="BorderElement" BorderBrush="{StaticResource TextBoxButtonBorderThemeBrush}" BorderThickness="{TemplateBinding BorderThickness}"/> 62 <Border x:Name="BackgroundElement" Background="{StaticResource TextBoxButtonBackgroundThemeBrush}" Margin="{TemplateBinding BorderThickness}"> 63 <TextBlock x:Name="GlyphElement" Foreground="{StaticResource TextBoxButtonForegroundThemeBrush}" FontFamily="{StaticResource SymbolThemeFontFamily}" HorizontalAlignment="Center" Text="" VerticalAlignment="Center"/> 64 </Border> 65 </Grid> 66 </ControlTemplate> 67 </Setter.Value> 68 </Setter> 69 </Style> 70 </Grid.Resources> 71 <Grid.ColumnDefinitions> 72 <ColumnDefinition Width="*"/> 73 <ColumnDefinition Width="Auto"/> 74 </Grid.ColumnDefinitions> 75 <VisualStateManager.VisualStateGroups> 76 <VisualStateGroup x:Name="WatermarkStates"> 77 <VisualState x:Name="WatermarkVisible"> 78 <Storyboard> 79 <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="PART_Watermark"> 80 <DiscreteObjectKeyFrame KeyTime="0"> 81 <DiscreteObjectKeyFrame.Value> 82 <Visibility>Visible</Visibility> 83 </DiscreteObjectKeyFrame.Value> 84 </DiscreteObjectKeyFrame> 85 </ObjectAnimationUsingKeyFrames> 86 </Storyboard> 87 </VisualState> 88 <VisualState x:Name="WatermarkCollapsed" /> 89 </VisualStateGroup> 90 <VisualStateGroup x:Name="CommonStates"> 91 <VisualState x:Name="Disabled"> 92 <Storyboard> 93 <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="BackgroundElement"> 94 <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TextBoxDisabledBackgroundThemeBrush}"/> 95 </ObjectAnimationUsingKeyFrames> 96 <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="BorderElement"> 97 <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TextBoxDisabledBorderThemeBrush}"/> 98 </ObjectAnimationUsingKeyFrames> 99 <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentElement"> 100 <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TextBoxDisabledForegroundThemeBrush}"/> 101 </ObjectAnimationUsingKeyFrames> 102 </Storyboard> 103 </VisualState> 104 <VisualState x:Name="Normal"> 105 <Storyboard> 106 <DoubleAnimation Duration="0" To="{StaticResource TextControlBackgroundThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BackgroundElement"/> 107 <DoubleAnimation Duration="0" To="{StaticResource TextControlBorderThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BorderElement"/> 108 </Storyboard> 109 </VisualState> 110 <VisualState x:Name="PointerOver"> 111 <Storyboard> 112 <DoubleAnimation Duration="0" To="{StaticResource TextControlPointerOverBackgroundThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BackgroundElement"/> 113 <DoubleAnimation Duration="0" To="{StaticResource TextControlPointerOverBorderThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BorderElement"/> 114 </Storyboard> 115 </VisualState> 116 <VisualState x:Name="Focused"/> 117 </VisualStateGroup> 118 <VisualStateGroup x:Name="ButtonStates"> 119 <VisualState x:Name="ButtonVisible"> 120 <Storyboard> 121 <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="DeleteButton"> 122 <DiscreteObjectKeyFrame KeyTime="0"> 123 <DiscreteObjectKeyFrame.Value> 124 <Visibility>Visible</Visibility> 125 </DiscreteObjectKeyFrame.Value> 126 </DiscreteObjectKeyFrame> 127 </ObjectAnimationUsingKeyFrames> 128 </Storyboard> 129 </VisualState> 130 <VisualState x:Name="ButtonCollapsed"/> 131 </VisualStateGroup> 132 </VisualStateManager.VisualStateGroups> 133 <Border x:Name="BackgroundElement" Background="{TemplateBinding Background}" Grid.ColumnSpan="2" Margin="{TemplateBinding BorderThickness}"/> 134 <Border x:Name="BorderElement" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Grid.ColumnSpan="2"/> 135 <ScrollViewer x:Name="ContentElement" HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}" HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}" IsTabStop="False" Margin="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}" VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}" ZoomMode="{TemplateBinding ScrollViewer.ZoomMode}"/> 136 <ContentPresenter x:Name="PART_Watermark" 137 Content="{TemplateBinding Watermark}" ContentTemplate="{TemplateBinding Watermark}" 138 IsHitTestVisible="False" Margin="{TemplateBinding Padding}" Visibility="Collapsed"/> 139 <Button x:Name="DeleteButton" BorderThickness="{TemplateBinding BorderThickness}" Grid.Column="1" FontSize="{TemplateBinding FontSize}" IsTabStop="False" Style="{StaticResource DeleteButtonStyle}" Visibility="Collapsed" VerticalAlignment="Stretch"/> 140 </Grid> 141 </ControlTemplate> 142 </Setter.Value> 143 </Setter> 144 </Style>
1 <StackPanel Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> 2 <local:WatermarkTextBox FontSize="12"> 3 <local:WatermarkTextBox.Watermark> 4 <StackPanel Orientation="Horizontal"> 5 <Image Source="ms-appx:///Asstes/edit.jpg"/> 6 <TextBlock Text="Edit Text" Foreground="Red" FontSize="20" Margin="4,0,0,0" /> 7 </StackPanel> 8 </local:WatermarkTextBox.Watermark> 9 </local:WatermarkTextBox> 10 </StackPanel>