WPF TextBox水印问题:初始化赋值与输入时水印未自动隐藏
WPF TextBox水印问题解决
问题描述
- 构造函数中设置
searchBox.Text = "aaa"后,运行时文本不显示,水印仍存在 - 用户输入内容时,输入文本与水印“Hello World”同时显示
核心原因
- 自定义
ControlTemplate中的水印TextBlock固定显示,未根据TextBox的Text内容动态控制可见性 - TextBox的
Text属性绑定了SearchText,直接设置控件的Text会被绑定逻辑覆盖,导致赋值无效
解决方案
1. 修改XAML:动态控制水印可见性
在ControlTemplate中添加触发器,默认隐藏水印,仅当TextBox的Text为空或null时显示水印:
<!-- 在Window/UserControl根元素添加系统命名空间(用于空字符串判断) --> xmlns:sys="clr-namespace:System;assembly=mscorlib" <!-- 修改后的TextBox完整XAML --> <TextBox x:Name="searchBox" HorizontalAlignment="Center" VerticalAlignment="Top" Width="1100" Height="30" Margin="10,70,0,0" FontSize="16" TextChanged="searchBox_TextChanged"> <TextBox.Style> <Style TargetType="TextBox"> <Setter Property="Background" Value="Transparent" /> <Setter Property="MaxLength" Value="50" /> <Setter Property="Foreground" Value="DarkGray" /> <Style.Triggers> <Trigger Property="IsFocused" Value="True"> <Setter Property="Foreground" Value="Black" /> </Trigger> </Style.Triggers> </Style> </TextBox.Style> <TextBox.Text> <Binding Path="SearchText" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"/> </TextBox.Text> <TextBox.Template> <ControlTemplate TargetType="TextBox"> <Grid> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"/> <!-- 默认隐藏水印 --> <TextBlock x:Name="Watermark" Text="Hello World" Foreground="LightGray" Margin="5,0,0,0" Visibility="Collapsed"/> <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" /> </Grid> <ControlTemplate.Triggers> <!-- 当Text为空或null时显示水印 --> <Trigger Property="Text" Value=""> <Setter TargetName="Watermark" Property="Visibility" Value="Visible"/> </Trigger> <Trigger Property="Text" Value="{x:Null}"> <Setter TargetName="Watermark" Property="Visibility" Value="Visible"/> </Trigger> <Trigger Property="Text" Value="{x:Static sys:String.Empty}"> <Setter TargetName="Watermark" Property="Visibility" Value="Visible"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </TextBox.Template> </TextBox>
2. 修改C#代码:通过绑定属性赋值
由于TextBox的Text已绑定到SearchText,需通过绑定属性赋值而非直接操作控件,同时实现INotifyPropertyChanged确保UI更新:
using System.ComponentModel; using System.Runtime.CompilerServices; using System.Windows; using System.Collections.Generic; using System.Linq; public partial class MainWindow : Window, INotifyPropertyChanged { private string _searchText; public string SearchText { get => _searchText; set { _searchText = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } // 示例:假设已定义的进程字典 private Dictionary<int, ProcessInfo> processDictionary = new Dictionary<int, ProcessInfo>(); public MainWindow() { InitializeComponent(); DataContext = this; // 设置数据上下文关联绑定属性 SearchText = "aaa"; // 通过绑定属性赋值,确保UI同步 } private void searchBox_TextChanged(object sender, TextChangedEventArgs e) { string searchText = searchBox.Text.ToLower(); var filteredProcesses = processDictionary.Values.Where(p => p.Name.ToLower().Contains(searchText)).ToList(); lstvw.ItemsSource = filteredProcesses; } } // 示例:自定义进程信息实体类 public class ProcessInfo { public string Name { get; set; } }
效果验证
- 构造函数赋值
SearchText = "aaa"后,TextBox显示"aaa",水印自动隐藏 - 用户输入内容时,水印立即隐藏,仅显示输入文本
- 清空文本后,水印重新显示
内容的提问来源于stack exchange,提问作者Daniel Lip
相关产品推荐
相关产品推荐

