Ошибки проверки WPF: настройка всплывающей подсказки с сообщением об ошибке
Почему нет текста всплывающей подсказки об ошибках?
<Style TargetType="{x:Type TextBox}">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<StackPanel>
<Border ...>
<AdornedElementPlaceholder ...
ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
</Border>
...
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Я также заметил, что
<AdornedElementPlaceholder ...
ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
не удается, но приведенные ниже результаты даже при одинаковом связывании почему так? не AdornedElementPlaceholder
ссылаетесь на текстовое поле? Даже если это не так, не должна ли всплывающая подсказка где-нибудь появиться?
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
</Trigger>
</Style.Triggers>
3 ответа
Вы не можете поместить всплывающую подсказку на AdornedElementPlaceholder, я не думаю, что она вообще видна, это просто резервирование места для того, кто ее использует (в вашем случае TextBox). Глядя на дерево визуалов с помощью Snoop, мы видим, что TemplatedAdorner оказывается в другом месте в VisualTree, чем TextBox, поэтому теперь у нас будет возможность найти TextBox из VisualTree. Мы можем найти его через AdornedElement, но все равно не сможем установить всплывающую подсказку.
Единственная вещь, видимая здесь в TemplatedAdorner - это Граница. Граница знает своего потомка - TemplatedAdorner - который, в свою очередь, знает свой AdornedElement - TextBox. Таким образом, мы могли бы установить всплывающую подсказку для границы с этим. (Тем не менее, эта привязка, по-видимому, не обновляет всплывающую подсказку для границы. Она работает, когда я смотрю на нее с помощью Snoop и после этого она отображается.)
<Border BorderBrush="Red"
BorderThickness="4"
ToolTip="{Binding RelativeSource={RelativeSource self},
Path=Child.AdornedElement.(Validation.Errors)[0].ErrorContent}">
Итак, TextBox имеет свою проверку AttachedProperty, где мы можем найти ErrorContent, поэтому он должен установить свою собственную подсказку, как вы делали в последнем примере, иначе он не будет работать.
Я знаю, что опоздал, но позвольте мне поделиться решением, которое я нашел, изучая этот вопрос: пользовательский валидатор WPF с всплывающей подсказкой.
В простейшей форме это ErrorTemplate
показывает только Tooltip
с ErrorContent
в целом AdornedElement
,
<ControlTemplate x:Key="validationTemplate">
<Grid Background="Transparent"
ToolTip="{Binding Path=/ErrorContent}">
<AdornedElementPlaceholder />
</Grid>
</ControlTemplate>
Но, конечно, вы можете украсить его по желанию, например, с Tooltip
только для маркера.
<ControlTemplate x:Key="validationTemplate">
<Grid>
<Ellipse Fill="Red" Opacity="0.8" Width="10" Height="10"
HorizontalAlignment="Right" VerticalAlignment="Top"
ToolTip="{Binding Path=/ErrorContent}" />
<AdornedElementPlaceholder />
</Grid>
</ControlTemplate>
Положи это Template
в Resources
и все, что вам нужно сделать, это установить Validation.ErrorTemplate
,
Validation.ErrorTemplate="{StaticResource validationTemplate}"
Даже этот раздражающий триггер больше не нужен.
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
</Trigger>
</Style.Triggers>
Я нашел способ реализовать
ToolTip
с возвращенным сообщением об ошибке от класса проверки, который вы можете создать для проверки введенных вами данных.
Во-первых: привязка сообщения об ошибке
Добавление
<Style>
для с
Style.Trigger
как следует:
<Style TargetType="{x:Type TextBox}" x:Key="ToolTipError">
<!-- Some style setters -->
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
Во-вторых: добавьте стиль в
TextBox
<TextBox
Style="{StaticResource ToolTipError}"
Validation.ErrorTemplate="{StaticResource validationTemplate}">
<TextBox.Text>
<Binding
Path="YourViewModelProperty"
UpdateSourceTrigger="PropertyChanged"
ValidatesOnNotifyDataErrors="True"
ValidatesOnDataErrors="True"
NotifyOnValidationError="True">
<Binding.ValidationRules>
<ExceptionValidationRule:DateValidationRule ValidatesOnTargetUpdated="True"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
Бонус!
Вы можете изменить некрасивую красную рамку на что-нибудь другое. Например, вы можете изменить его на красный восклицательный знак:
<Window.Resources>
<ControlTemplate x:Key="validationTemplate">
<StackPanel>
<TextBlock Text="!" FontSize="26" Foreground="Red"/>
<AdornedElementPlaceholder/>
</StackPanel>
</ControlTemplate>
<Window.Resources>