最近在做WPF,有个需求需要动态生成TextBox,实现很简单,只需要把TextBox动态添加到ListBox中就可以了。后来对方说要在TextBox中显示水印,想了很多办法。
首先WPF中我并没有发现可以直接使用水印的方法,其次网上的很多教程都是写在前端(XAML定义)的,而且是每一个TextBox都需要定义对应的style,对于后台代码实现起来很麻烦。因此对于动态加载的TextBox不易实现水印。
在查了很多网上的资料后,我发现一种方法我可以借鉴。
<ControlTemplate x:Key="WaterMarkTextBox" TargetType="{x:Type 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="InternalWatermarkLabel"
Text="{TemplateBinding Tag}"
FontStyle="Italic"
Visibility="Collapsed" Focusable="False"
Foreground="Silver"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsFocused" Value="False" />
<Condition Property="Text" Value="" />
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Visibility" TargetName="InternalWatermarkLabel" Value="Visible" />
</MultiTrigger.Setters>
</MultiTrigger>
<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>
<TextBox Grid.Row="0" Grid.Column="1" Margin="0,15" Text="abcdefg" x:Name="tb_PassPhrase" VerticalAlignment="Center"
Tag="Pass Phrase" Template="{DynamicResource WaterMarkTextBox}">
</TextBox>
如上先定义一段资源样式,在TextBox中只需要使用 Tag和Template就可以完成水印的功能,而且后台代码很容易实现。具体实现如下:
1、先在前台使用XAML定义这段样式
<Grid.Resources>
<ControlTemplate x:Key="WaterMarkTextBox" TargetType="{x:Type 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="InternalWatermarkLabel"
Text="{TemplateBinding Tag}"
FontStyle="Italic"
Visibility="Collapsed" Focusable="False"
Foreground="Silver"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsFocused" Value="False" />
<Condition Property="Text" Value="" />
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Visibility" TargetName="InternalWatermarkLabel" Value="Visible" />
</MultiTrigger.Setters>
</MultiTrigger>
<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>
</Grid.Resources>
2、后台只需在new TextBox时,添加tag和Template的属性即可。
TextBox tb = new TextBox();
tb.Width = 200;
tb.Tag = Tishi[i];
tb.SetResourceReference(TextBox.TemplateProperty, "WaterMarkTextBox");
Tag就是水印的内容,WaterMarkTextBox就是引用的资源Key。
这样就可以了,并不是老手,如果表达欠妥,请多多批评和指正。