将 ErrorTemplate 添加到 WPF 用户控件会禁用 TextBox 输入

Adding an ErrorTemplate to a WPF User Control disables TextBox input

我有一个非常基本的自定义控件,由一个标签和一个文本框组成。我已经使用我的控件一段时间了,没有任何问题。

我现在开始设计我的应用程序的样式,并将我的样式放在仅包含 ResourceDictionary 的 XAML 文件中。我的用户控件有以下内容:

<Style TargetType="local:LabelEdit">
    <Setter Property="Background" Value="{StaticResource BackgroundBrush}" />
    <Setter Property="Foreground" Value="{StaticResource ForegroundBrush}" />
    <Setter Property="BorderBrush" Value="{StaticResource BorderBrush}" />

    <Setter Property="Validation.ErrorTemplate">
        <Setter.Value>
            <ControlTemplate>
                <StackPanel>
                    <AdornedElementPlaceholder />
                    <Image Source="/AJSoft.Controls;component/Resources/Icons/cross.ico" />
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>

    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="True">
            <Setter Property="Foreground" Value="{StaticResource ErrorForegroundBrush}" />
            <Setter Property="Background" Value="{StaticResource ErrorBackgroundBrush}" />
            <Setter Property="BorderBrush" Value="{StaticResource ErrorBorderBrush}" />
        </Trigger>
    </Style.Triggers>
</Style>

如果我将 Validation.ErrorTemplate 的 Setter 注释掉,则一切正常。如果 ErrorTemplate 完好无损,则会显示十字(我还没有确定位置,但稍后会出现...),但我的 UserControl 的文本框组件不显示插入符号或接受键盘输入。我的 Window 中的其余控件按预期工作。

以下是我故意放入一些错误文本以显示其外观的屏幕截图。

即使我将那个巨大的图像更改为带有红色小“!”的文本块,也会出现同样的问题。 - 图片仅供参考。

我在做什么导致了这个问题?我是 WPF 中验证的新手...

编辑:显示的图像(大红叉)只是我所做的一个例子。即使我使用与 UserControl 一起显示的小图像,我仍然会得到相同的效果。

如果您查看错误模板通常是如何工作的,您会发现它们适用于单个控件。 您在这里遇到的部分问题是您在一个父用户控件中有一个标签和文本框。 如果您随后在用户控件级别应用错误模板,它会出现在其中的所有内容上。标签,文本框,用户控件中的所有内容。

接下来要考虑的是您的错误模板如何最终显示在所有内容之上。发生这种情况是因为您的错误模板在装饰层中生成了 UI。这是最重要的(在 window 中)。 将这些加在一起,您将在用户控件的内容之上得到一个大图像。

存在过度简化的风险:

你在你的盒子上放了一个顶部,你现在看不到那个盒子里有什么。

有几种方法可以“解决”这个问题,但它们都涉及一些设计更改或妥协。 也许在输入控件上加一个大 X 不是个好主意。 你可以让它发挥作用。

您可以使图像 IsHitTestVisible="False"。 它会以视觉方式出现,但您随后可以单击文本框并键入。 只是也许看不到一切。 可能不太理想。

您可以使用数据触发器而不是错误模板在文本框旁边显示您的十字。 将图像添加到您的用户控件,以便您拥有标签、文本框和 CrossImage。 添加一个带有 setter 的样式,使其在默认情况下可见。 使用该样式的触发器在控件出错时显示 CrossImage。

 <Style.Triggers>
    <Trigger Property="Validation.HasError" Value="true">
        <Setter ... />
    </Trigger>
 </Style.Triggers>

您可能会发现最简单的方法是在用户控件上使用标签并将其设置为 visible/collapsed。将图像的可见性绑定到那个。