之前那个版本《silverlight-带水印的TextBox》不得不说是相当失败的,起码我是这样理解的。其实我一心想把这个给实现了,但是不得不承认自身技术上的缺陷。经过一番尝试和折腾,有了下面这个版本。
两个版本的区别:
其实是有本质的区别的。
之前那个版本只能设置“文本水印”,相当有局限性。现在的版本是可以自定义水印内容的。譬如,可以为button,rectangle,ellipsed...
1.先新建一个“silverlight 模板化控件”,取名随意,此处为SuperText
2.修改继承的类Contol为TextBox
3.修改TextBox模板
控件SuperTextBox的模板,样式都是保存在一个叫“Generic.xaml”文件里面的。在第一次新建“silverlight 模板化控件”的时候,这个文件会自动产生。这里将TextBox的模板添加进入,并修改。
完整的
完整的Generic.xaml
在上面的"Generic.xaml"文件的SuperTextBox模板中修改新增了一下内容
- 新增一个UserControl,即水印内容。
取名随意,这里为“watermarkContent”,并且绑定Content属性为“WaterMark”
<UserControl x:Name="watermarkContent" Content="{TemplateBinding Watermark}"/>
- 增加两个状态
状态为了控制水印是否出现。其实本质是调节水印的透明度。
<VisualStateGroup x:Name="WatermarkDisplayed">
<VisualState x:Name="Hidden">
<Storyboard>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="watermarkContent" Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Shown">
<Storyboard>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="watermarkContent" Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="1" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
4.在托管代码中
- 因为模板中绑定了一个新的属性WaterMark,所以需要在托管代码进行注册。并且用属性Watermark保存。
public object Watermark { get { return base.GetValue(WatermarkProperty) as object; } set { base.SetValue(WatermarkProperty, value); } } //向空间增加property public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register("Watermark", typeof(object), typeof(SuperTextBox), new PropertyMetadata(null));
- 为了控制水印状态需要增加一个TextChanged事件。
public SuperTextBox() { this.DefaultStyleKey = typeof(SuperTextBox); TextChanged += new TextChangedEventHandler(SuperTextBox_TextChanged); } void SuperTextBox_TextChanged(object sender, TextChangedEventArgs e) { TextBox tb = (TextBox)sender; if (tb.Text.Length > 0) { System.Windows.VisualStateManager.GoToState(tb, "Hidden", false); } else { System.Windows.VisualStateManager.GoToState(tb, "Shown", false); } }
- 完整托管代码
完整的SuperTextBox托管代码
5.调用
<local:SuperTextBox Height="20">
<local:SuperTextBox.Watermark>
<StackPanel Orientation="Horizontal" Opacity="0.4">
<Rectangle Fill="Red" Width="10" Height="10"/>
<TextBlock Text="我是一个水印"/>
</StackPanel>
</local:SuperTextBox.Watermark>
</local:SuperTextBox>
需加上命名空间local,local指向的是SuperTextBox所在的命名空间。