WPF如何在TextBox上显示类似水印的提示占位符效果

在WPF中需要显示水印的效果,有时候需要显示在TextBox上显示类似水印的灰色提示文本占位符效果来作为提醒信息类似如下效果:


图1. 水印显示的效果

要实现这样的效果有很多办法,这里介绍一个最简单的,就是在TextBox上叠加一个TextBlock来实现这个功能,这里对比显示完全的实现过程:

  1. 原始的没有占位符效果的代码如下:
<StackPanel Orientation="Horizontal">
    <Label Content="Print Ran_ge:"/>
    <TextBox Text="{Binding PrintRange, UpdateSourceTrigger=PropertyChanged}" MinWidth="300" VerticalContentAlignment="Center" ToolTip="Serial number in format: 1,3-5,8" />
</StackPanel>
  1. 是轻松实现两个控件叠加的效果,Grid是最简单直接的,要显示在上面的注意放在Grid里的后面部分,越前面越在底层,这里TextBlock在TextBox的后面,所以它显示在TextBox的上面,就出现了如上图1的效果:
<StackPanel Orientation="Horizontal" >
    <Label Content="Print Ran_ge:"/>
    <Grid>
        <TextBox Text="{Binding PrintRange, UpdateSourceTrigger=PropertyChanged}" MinWidth="300" VerticalContentAlignment="Center" ToolTip="Serial number in format: 1,3-5,8" />
        <TextBlock Text="Serial number in format: 1,3-5,8" Visibility="{Binding ShowPrintRangeWaterMark}" VerticalAlignment="Center" Foreground="Gray" Padding="5,0" IsHitTestVisible="False"/>
    </Grid>
</StackPanel>

上面代码两个要点:
a. <TextBox Text="{Binding PrintRange, UpdateSourceTrigger=PropertyChanged}",这个让属性改变的触发实时发生,而不是在TextBox失去焦点才发生。
b. <TextBlock Text="Serial number in format: 1,3-5,8" Visibility="{Binding ShowPrintRangeWaterMark}" VerticalAlignment="Center" Foreground="Gray" Padding="5,0" IsHitTestVisible="False"/>,加粗部分让TextBlock不响应任何点击或者输入事件,它悬浮在那里,但它不影响下面的TextBox的键盘鼠标的操作。

  1. 功能的实现,功能的实现我们是通过两个控件绑定的两个属性来实现的,一个是TextBox的Text属性,它绑定了其视图模型的PrintRange属性,一个是TextBlock的Visibility属性,它绑定了其视图模型的ShowPrintRangeWaterMark属性。
    代码很简单,打开视图模型的类,添加两个上面提到的属性:
        private string _printRange;
        public string PrintRange
        {
            get => _printRange;
            set
            {
                _printRange = value;
                OnPropertyChanged(nameof(PrintRange));
                OnPropertyChanged(nameof(ShowPrintRangeWaterMark));
            }
        }

        public Visibility ShowPrintRangeWaterMark => string.IsNullOrEmpty(_printRange) ? Visibility.Visible : Visibility.Collapsed;

需要注意的是,这个视图模型一定要实现INotifyPropertyChanged接口,就是要这些代码:

   public class MyViewModel : INotifyPropertyChanged
   {
       public event PropertyChangedEventHandler PropertyChanged;
       protected virtual void OnPropertyChanged(string propertyName)
       {
           PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
       }

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容