Ошибки проверки 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>
Другие вопросы по тегам