错误模板上面其他控件显示,当它应该被隐藏(Error template is displayed a

2019-06-23 22:13发布

我试图实现使用我的WPF应用程序验证IDataErrorInfo界面,我已经遇到了一个不那么理想的情况。

我有这个模板,用于当控件无法验证

<ControlTemplate x:Key="errorTemplate">
    <DockPanel LastChildFill="true">
        <Border Background="Red" DockPanel.Dock="Right" Margin="5,0,0,0" Width="20" Height="20" CornerRadius="10"
                                    ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
            <TextBlock Text="!" VerticalAlignment="Center" HorizontalAlignment="Center" FontWeight="Bold" Foreground="White" />
        </Border>
        <AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" >
            <Border BorderBrush="red" BorderThickness="1" />
        </AdornedElementPlaceholder>
    </DockPanel>
</ControlTemplate>

一切都很好,直到我试图显示一些验证失败,如显示它上面的码头项目的控制上面:

我怎样才能避免这种情况,并显示在Dock项目我下面的错误模板,因为它应该?

编辑

我发现我可以总结我的TextBoxAdornerDecorator来解决这个问题,但我真的不希望为每一位做到这一点TextBox在我的应用程序的控制。 有可能的方式与设置Style或一些其他的方式?

编辑2

我大概可以更改默认TextBox控件模板,以包括AdornerDecorator ,但我不改变任何的WPF的默认控件模板过于激烈。 任何其他建议都欢迎。

Answer 1:

OK,我发现了一个比较简单的解决方案,不强迫我改变任何控制模板。

相反,每一个装饰的TextBoxAdornerDecorator这样

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

我可以有AdornerDecorator缠上了我的整个视图,可达到相同的结果。

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

这样我可以把它定义每个视图最多一次。



Answer 2:

基于@AdiLester伟大的答案,如果你的控件是从基类派生,你不希望把AdornerDecorator在每个控制的XAML,然后走这条路:

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;
        }
    }
}


Answer 3:

我会用一种风格,这里这里有一个你可以很容易适应的一个例子。

注意,ErrorContent选自(Validation.Errors).CurrentItem.ErrorContent到来,而不是错误[0]。 虽然两者都可以工作,与吞咽异常后者将垃圾你的输出窗口这里概述 。

<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>


文章来源: Error template is displayed above other controls, when it should be hidden