wpf 当Validation.HasError为true时使元素可见

ilmyapht  于 2022-12-05  发布在  其他
关注(0)|答案(1)|浏览(190)

我有下面的xaml标记:

<GroupBox Margin="10" Padding="20" Header="Case 5 - Custom Error Object">
                <GroupBox.DataContext>
                    <local:ViewModel4/>
                </GroupBox.DataContext>
                <StackPanel>
                    <Label Name="AdornerElement" Style="{StaticResource ResourceKey=AdornerElementStyle}"/>
                    <TextBox Text="{Binding Path=UserName, UpdateSourceTrigger=PropertyChanged, ValidatesOnNotifyDataErrors=True}"
                             Margin="0 10"
                             Validation.ValidationAdornerSite="{Binding ElementName=AdornerElement}">
                    </TextBox>
                </StackPanel>
            </GroupBox>

和以下样式:

<Style x:Key="AdornerElementStyle" TargetType="Label">
            <Setter Property="Visibility" Value="Collapsed"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Label">
                        <StackPanel Orientation="Horizontal" Background="LightCoral">
                            <Image Source="/clipart.png" Width="24" Margin="10"/>
                            <ItemsControl ItemsSource="{Binding ElementName=AdornerElement, Path=(Validation.ValidationAdornerSiteFor).(Validation.Errors)}"
                                      VerticalAlignment="Center">
                                <ItemsControl.ItemTemplate>
                                    <DataTemplate>
                                        <TextBlock Text="{Binding Path=ErrorContent.ValidationMessage}"
                                                   Style="{StaticResource CustomErrorTypeStyle}"/>
                                    </DataTemplate>
                                </ItemsControl.ItemTemplate>
                            </ItemsControl>
                        </StackPanel>
                        <ControlTemplate.Triggers>
                            <DataTrigger Binding="{Binding ElementName=AdornerElement, Path=Validation.HasError}" Value="True">
                                <Setter Property="Visibility" Value="Visible"/>
                            </DataTrigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

除了Trigger,一切都正常。
如果我最初将属性“Visibility”设置为“Visible”,则可以看到错误消息正确显示。

如果我使用之前显示的样式,则Label保持为折叠状态。
请帮助我正确地使用触发器来达到最终的结果。

lf5gs5x2

lf5gs5x21#

这不是Validation.ValidationAdornerSite的工作方式。这个附加的属性只定义了将用验证错误模板装饰的元素。默认情况下,这是正在验证的元素,更准确地说是Binding.Target
当您设定Validation.ValidationAdornerSite时,系结引擎会自动设定附加的Validation.ValidationAdornerSiteFor属性,以指涉最初设定Validation.ValidationAdornerSite的元素。
这意味着Validation.HasError和其他相关的附加属性始终在Binding.Target上设置,而不是在装饰器站点上设置。
这就是为什么你的触发器不起作用:它们在Label上触发,而不是在TextBox(注册验证/绑定错误的位置)上触发。
若要修正此问题,DataTrigger必须取得Validation.ValidationAdornerSiteFor附加属性的Validation.HasErrors附加属性值,此附加属性值会指涉原始Binding.TargetTextBox)。

<Style x:Key="AdornerElementStyle"
       TargetType="Label">
  <Setter Property="Visibility"
          Value="Collapsed" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="Label">
        <StackPanel Orientation="Horizontal"
                    Background="LightCoral">
          <Image Source="/clipart.png"
                 Width="24"
                 Margin="10" />
          <ItemsControl ItemsSource="{Binding ElementName=AdornerElement, Path=(Validation.ValidationAdornerSiteFor).(Validation.Errors)}"
                        VerticalAlignment="Center">
            <ItemsControl.ItemTemplate>
              <DataTemplate>
                <TextBlock Text="{Binding ErrorContent.ValidationMessage}" />
              </DataTemplate>
            </ItemsControl.ItemTemplate>
          </ItemsControl>
        </StackPanel>
        <ControlTemplate.Triggers>
          <DataTrigger Binding="{Binding ElementName=AdornerElement, Path=(Validation.ValidationAdornerSiteFor).(Validation.HasError)}"
                       Value="True">
            <Setter Property="Visibility"
                    Value="Visible" />
          </DataTrigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

备注

不清楚为什么要使用Label来显示错误消息。您可以简单地定义一个错误模板,即由附加的Validation.ErrorTemplate属性引用的ControlTemplate。这将大大简化您的代码。
下面的示例创建了完全相同的可视错误反馈,但没有额外的Label和关联的触发器来管理错误消息的可见性。所有这些都由WPF绑定引擎处理。

<Window>
  <Window.Resources>

    <!-- The Validation.Errors property is the DataContext of this template -->
    <ControlTemplate x:Key="ErrorTemplate">
      <StackPanel>
        <Border BorderBrush="Red"
                BorderThickness="1"
                Background="LightCoral">
          <StackPanel Orientation="Horizontal">
            <Image Source="/clipart.png"
                    Width="24"
                    Margin="10" />
            <ItemsControl ItemsSource="{Binding}"
                          VerticalAlignment="Center">
              <ItemsControl.ItemTemplate>
                <DataTemplate>
                  <TextBlock Text="{Binding ErrorContent.ValidationMessage}" />
                </DataTemplate>
              </ItemsControl.ItemTemplate>
            </ItemsControl>
          </StackPanel>
        </Border>

        <Border BorderBrush="Transparent"
                BorderThickness="1"
                HorizontalAlignment="Left">

          <!-- Placeholder for the Binding.Target -->
          <AdornedElementPlaceholder x:Name="AdornedElement" />
        </Border>
      </StackPanel>
    </ControlTemplate>
  </Window.Resource>

  <StackPanel>
    <TextBox Text="{Binding Path=UserName, UpdateSourceTrigger=PropertyChanged, ValidatesOnNotifyDataErrors=True}"
             Validation.ErrorTemplate="{StaticResoucre ErrorTemplate}" />
  </StackPanel>
</Window>

相关问题