WPF中ErrorTemplate的Tooltip仅在Border显示,TextBox内不显示的问题
问题
我有一个绑定整数属性的TextBox控件,代码如下:
<TextBox x:Name="txtInteger" Grid.Row="2" Grid.Column="0" Text="{Binding Path=IntegerValue}" Validation.ErrorTemplate="{StaticResource ValidationForNumericValues}"/>
对应的验证错误模板ValidationForNumericValues定义如下:
<Window.Resources> <ControlTemplate x:Key="ValidationForNumericValues"> <Grid> <Border BorderThickness="1" BorderBrush="Red"> <Border.ToolTip> <ToolTip Placement="Right" HorizontalOffset="5" VerticalOffset="5" Content="Please enter a number"/> </Border.ToolTip> <AdornedElementPlaceholder/> </Border> </Grid> </ControlTemplate> </Window.Resources>
当在txtInteger中输入非整数值时,红色边框正常显示,但鼠标处于TextBox内部时Tooltip不显示,仅在红边框上方才会触发显示。
我尝试过移除相关<Style.../>声明、添加TextBlock修改模板、设置AdornedElementPlaceholder的Tooltip、绑定TextBox的Tooltip属性等方法,均未解决问题,且部分方法会导致TextBox无法点击获焦。
开发环境为Visual Studio 2019下的.NET 5.0项目,请问问题出在哪里?
原因与解决方案
问题根源
验证错误模板里的Border是位于AdornedElementPlaceholder(即TextBox本身)的上层视觉元素,但TextBox作为交互控件会优先捕获鼠标事件,导致鼠标在TextBox内部时,下方的Border接收不到触发Tooltip的鼠标事件,只有鼠标直接停在Border未被TextBox覆盖的边框区域时,Tooltip才会触发。
解决方法
方案1:给AdornedElementPlaceholder绑定Tooltip
直接将Tooltip附加到被装饰的TextBox上,同时保留红色边框的视觉效果,修改后的模板代码如下:
<Window.Resources> <ControlTemplate x:Key="ValidationForNumericValues"> <Grid> <Border BorderThickness="1" BorderBrush="Red"/> <AdornedElementPlaceholder> <AdornedElementPlaceholder.ToolTip> <ToolTip Placement="Right" HorizontalOffset="5" VerticalOffset="5" Content="Please enter a number"/> </AdornedElementPlaceholder.ToolTip> </AdornedElementPlaceholder> </Grid> </ControlTemplate> </Window.Resources>
此方案下,Tooltip会绑定到TextBox本体,鼠标在TextBox内部或边框区域都会触发Tooltip显示,红色边框的渲染不受影响。
方案2:让Border不拦截鼠标事件
给Border添加IsHitTestVisible="False",使其仅作为视觉装饰、不参与交互,鼠标事件会穿透Border到下方的TextBox,同时将Tooltip绑定到外层Grid:
<Window.Resources> <ControlTemplate x:Key="ValidationForNumericValues"> <Grid> <Border BorderThickness="1" BorderBrush="Red" IsHitTestVisible="False"/> <AdornedElementPlaceholder/> <Grid.ToolTip> <ToolTip Placement="Right" HorizontalOffset="5" VerticalOffset="5" Content="Please enter a number"/> </Grid.ToolTip> </Grid> </ControlTemplate> </Window.Resources>
这个方案中,鼠标悬停在整个验证区域(包括TextBox内部)时,都会触发Grid的Tooltip显示。
内容的提问来源于stack exchange,提问作者Jean-David Lanz

