首页 > 解决方案 > 更改选项卡时 WPF 验证停止工作

问题描述

我有一个 WPF 应用程序,其中有一个TabControl,并且在某个选项卡中有一个TextBox带有验证规则的。

验证规则工作正常,转换器工作正常,绑定也可以。
但是当我这样做时会发生一个非常烦人的错误(可能与 WPF 本身有关):

验证完全停止工作,直到我输入有效文本,然后它再次开始工作。更改文本是不够的,如果我输入有效文本,它只会重新开始工作。

输入选项卡时如何强制重新验证文本?


我已经尝试了此处列出的两种解决方案,但它们似乎没有带红色边框:

如果需要,这是 XAML 的简要说明:

<TabControl ...>
    <TabItem ... />
    <TabItem ...>
        ...
        <TextBox Name="txtName" ...>
            <TextBox.Text>
                <Binding Path="..." 
                         UpdateSourceTrigger="PropertyChanged" 
                         Mode="OneWayToSource"
                         FallbackValue="5"
                         Converter="MyCustomConverterWorkingOk">

                     <Binding.ValidationRules>
                         <local:MyCustomValidationWorkingOk/>
                     </Binding.ValidationRules>
                </Binding> 
            </TextBox.Text>
        </TextBox>
    </TabItem>
</TabControl>

标签: c#wpfvalidationdata-binding

解决方案


这种行为的原因是TabControl显示其内容的方式:所有选项卡共享相同的ContentPresenter. 在选项卡之间导航时,旧内容将被完全删除。对于AdornerLayer在其上呈现错误模板的 也是如此。由于AdornerLayer是无状态的并且TabControl不监视所有可能的装饰器,因此无法恢复先前选项卡内容的旧呈现错误模板。

您有三个不错的选择:

  1. 除非选项卡的数据处于有效状态,否则不允许用户离开选项卡或
  2. 离开选项卡时丢弃无效数据(这也会重置相关错误)或
  3. 在切换回包含无效数据输入的 a 时强制AdornerLayer重新渲染。TabItem

以下示例显示了如何在装饰元素可见时强制再次AdornerLayer渲染所有元素的装饰器:TextBox

<!-- Custom error template -->
<ControlTemplate x:Key="ValidationErrorTemplate">
  <StackPanel>

    <!-- Placeholder for the TextBox itself -->
    <AdornedElementPlaceholder />

    <TextBlock Text="{Binding ErrorContent}"
               Foreground="Red" />
  </StackPanel>
</ControlTemplate>

<!-- Style to trigger the rendering of the AdornerLayer by setting the error template -->
<Style TargetType="TextBox">
  <Setter Property="Validation.ErrorTemplate"
          Value="{x:Null}" />
  <Style.Triggers>
    <MultiTrigger>
      <MultiTrigger.Conditions>
        <Condition Property="Validation.HasError"
                   Value="True" />
        <Condition Property="IsVisible"
                   Value="True" />
      </MultiTrigger.Conditions>
      <Setter Property="Validation.ErrorTemplate"
              Value="{StaticResource ValidationErrorTemplate}" />
    </MultiTrigger>
  </Style.Triggers>
</Style>

推荐阅读