Validation.ErrorTemplate,用于访问AdornedElementPlaceholder上的属性

时间:2014-10-06 17:24:10

标签: wpf validation xaml binding errortemplate

我希望我的错误模板看起来有所不同,具体取决于装饰控件上的某些属性值。

如下所示设置TargetType会导致运行时异常:'TextBox'ControlTemplate TargetType与模板化类型'Control'不匹配。因此,似乎ErrorTemplate必须使用targetType为“Control”。

<ControlTemplate x:Key="ValidationErrorTemplate" TargetType={x:Type TextBox}>
  <Grid>
    <AdornedElementPlaceholder  HorizontalAlignment="Left" Name="placeholder"/>
    <Grid Background="Yellow">
      <Grid.Style>
        <Style TargetType="Grid">
          <Style.Triggers>
            <DataTrigger Binding="{TemplateBinding IsReadOnly}" Value="True">
              <Setter Property="Background" Value="Green"/>
            </DataTrigger>
          </Style.Triggers>
        </Style>
      </Grid.Style>
    </Grid>
  </Grid>
</ControlTemplate>

我删除了targetType,然后尝试了这个:

<DataTrigger Binding="{Binding IsReadOnly, RelativeSource={RelativeSource AncestorType={x:Type TextBox}}}" Value="True">
  <Setter Property="Background" Value="Green"/>
</DataTrigger>

然后这个,没有例外但也没有效果:

<DataTrigger Binding="{Binding AdornedElement.(TextBox.IsReadOnly), ElementName=placeholder}" Value="True">
  <Setter Property="Background" Value="Orange"/>
</DataTrigger>

而且,这没有例外但也没有效果:

<DataTrigger Binding="{Binding (TextBox.IsReadOnly), ElementName=placeholder}" Value="True">
  <Setter Property="Background" Value="Orange"/>
</DataTrigger>

最后这个,它产生了“BindingExpression路径错误:'IsReadOnly'属性在'object'''AdornedElementPlaceholder'上找不到”:

<DataTrigger Binding="{Binding IsReadOnly, ElementName=placeholder}" Value="True">
  <Setter Property="Background" Value="Green"/>
</DataTrigger>

有没有人对如何在ErrorTemplate中引用依赖项属性有任何其他想法?

1 个答案:

答案 0 :(得分:2)

正确答案是:

<DataTrigger Binding="{Binding AdornedElement.(TextBox.IsReadOnly), ElementName=placeholder}" Value="True">
  <Setter Property="Background" Value="Orange"/>
</DataTrigger>

虽然这是我早期失败的尝试之一,但我的测试设置存在缺陷。我在网格上设置默认背景属性,而不是在样式中设置它。由于依赖属性优先级,直接在对象上设置的值将始终优先于样式中设置的任何值(特别是在我的触发器中)。

这是一个有效的设置:

<ControlTemplate x:Key="ValidationErrorTemplate">
  <Grid>
    <Grid.Style>
      <Style TargetType="{x:Type Grid}">
        <Setter Property="Background" Value="Yellow"/>
        <Style.Triggers>
          <DataTrigger Binding="{Binding AdornedElement.(TextBox.IsReadOnly), ElementName=placeholder}" Value="True">
            <Setter Property="Background" Value="Orange"/>
          </DataTrigger>
        </Style.Triggers>
      </Style>
    </Grid.Style>

    <AdornedElementPlaceholder Name="placeholder"/>
  </Grid>
</ControlTemplate>

这里的一个关键是AdornedElement始终是Control类型,因此您必须进行适当的限定(或转换?)以访问未在Control上公开的属性。这是通过类名和属性周围的括号完成的。另一个例子是:AdornedElement。(CheckBox.IsChecked)。由于IsChecked不在Control上,因此您必须通过明确声明拥有该属性的类类型来限定它。