Error template is displayed above other controls, when it should be hidden

淺唱寂寞╮ 提交于 2019-11-30 06:42:48

OK, I found a relatively simple solution which doesn't force me to change any control templates.

Instead of decorating each TextBox with an AdornerDecorator like this

<StackPanel>
    <AdornerDecorator>
        <TextBox Text={Binding ...} />
    </AdornerDecorator>
    <AdornerDecorator>
        <TextBox Text={Binding ...} />
    </AdornerDecorator>
</StackPanel>

I can have the AdornerDecorator wrap my entire view, which achieves the same result.

<AdornerDecorator>
    <StackPanel>
        <TextBox Text={Binding ...} />
        <TextBox Text={Binding ...} />
    </StackPanel>
</AdornerDecorator>

This way I can define it at most one time per view.

Based on @AdiLester great answer, if your controls are deriving from a base class and you don't want to put AdornerDecorator in XAML of each control, then go this way:

public class MyBaseUserControl : UserControl
{
    public MyBaseUserControl()
    {

    }

    protected override void OnContentChanged(object oldContent, object newContent)
    {
        base.OnContentChanged(oldContent, newContent);

        if (!(newContent is AdornerDecorator))
        {
            this.RemoveLogicalChild(newContent);

            var decorator = new AdornerDecorator();
            decorator.Child = newContent as UIElement;

            this.Content = decorator;
        }
    }
}

I would use a style, and here here's an example of one that you can easily adapt.

Note that the ErrorContent is coming from (Validation.Errors).CurrentItem.ErrorContent as opposed to Errors[0]. Although both will work, the latter will litter your output window with swallowed exceptions as outlined here.

<Style x:Key="TextBoxStyle" TargetType="{x:Type TextBox}">
    <Setter Property="Margin" Value="0,0,16,0" />
    <Setter Property="VerticalAlignment" Value="Center" />
    <Setter Property="VerticalContentAlignment" Value="Center" />

    <!--
    Error handling
    -->
    <Setter Property="Validation.ErrorTemplate">
        <Setter.Value>
            <ControlTemplate>
                <DockPanel LastChildFill="True">
                    <TextBlock DockPanel.Dock="Right" Text=" *" 
                               Foreground="Red" FontWeight="Bold" FontSize="16" 
                               ToolTip="{Binding ElementName=placeholder, Path=AdornedElement.(Validation.Errors).CurrentItem.ErrorContent}"/>
                    <Border BorderBrush="Red"  BorderThickness="1">
                        <AdornedElementPlaceholder Name="placeholder"></AdornedElementPlaceholder>
                    </Border>
                </DockPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="True">
            <Setter Property="Background" Value="LightYellow"/>
        </Trigger>
    </Style.Triggers>
</Style>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!