WPF嵌套绑定在controltemplate中

时间:2011-08-17 22:22:06

标签: wpf templates xaml binding templatebinding

我已经成功创建了一个文本框,根据模型/ vm中设置的验证规则显示/折叠错误消息。对于例如:

的电子邮件,代码如下所示
    <StackPanel Grid.Row="3" Grid.Column="1">
        <TextBox MaxLength="200" x:Name="mailTextBox"
                Style="{StaticResource SectionEditPropertyTextBox}"
                Text="{Binding Email, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
        <ContentPresenter Visibility="{Binding ElementName=mailTextBox, Path=(Validation.HasError), Converter={StaticResource BooleanToVisibilityConverter}, ConverterParameter=True }"
                Content="{Binding ElementName=mailTextBox, Path=(Validation.Errors).CurrentItem}"
                HorizontalAlignment="Left">
            <ContentPresenter.ContentTemplate>
                <DataTemplate>
                    <Label Style="{StaticResource SectionEditErrorLabel}" Content="{Binding Path=ErrorContent}"/>
                </DataTemplate>
            </ContentPresenter.ContentTemplate>
        </ContentPresenter>
    </StackPanel>

由于我有很多这些,我本来希望将所有这些放在一个控制模板中,并将其重新定位在一个公共资源文件中。

我的模板如下所示:

<ControlTemplate x:Key="FormTextBox" TargetType="{x:Type TextBox}">
    <StackPanel Grid.Row="{TemplateBinding Grid.Row}" Grid.Column="{TemplateBinding Grid.Column}">
        <TextBox x:Name="validableText" MaxLength="{TemplateBinding MaxLength}"
                Style="{StaticResource SectionEditPropertyTextBox}"
                Text="{TemplateBinding Text}" />
        <ContentPresenter Visibility="{Binding ElementName=validableText, Path=(Validation.HasError), Converter={StaticResource BooleanToVisibilityConverter}, ConverterParameter=True }"
                Content="{Binding ElementName=validableText, Path=(Validation.Errors).CurrentItem}"
                HorizontalAlignment="Left">
            <ContentPresenter.ContentTemplate>
                <DataTemplate>
                    <Label Style="{StaticResource SectionEditErrorLabel}" Content="{Binding Path=ErrorContent}"/>
                </DataTemplate>
            </ContentPresenter.ContentTemplate>
        </ContentPresenter>
    </StackPanel>
</ControlTemplate>

我这样链接到它:

    <TextBox Grid.Row="3" Grid.Column="1" MaxLength="200" Template="{StaticResource FormTextBox}"
             Text="{Binding Email, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />

不幸的是,它没有执行任何验证,因此必须以某种方式破坏绑定......

请告知......

感谢。

1 个答案:

答案 0 :(得分:5)

您不需要模板StackPanel中的Grid.RowGrid.Column绑定,因为StackPanel不会是Grid的直接子节点,

TemplateBinding始终是OneWay绑定,因此模板化Text的{​​{1}}属性永远不会更新。使用TextBoxRelativeSource

将其更改为常规绑定

TwoWay的绑定中将ElementName=validableText更改为RelativeSource={RelativeSource TemplatedParent},因为我们要对Templated ContentPresenter而不是TextBox内的TextBox执行验证检查模板。

<ControlTemplate x:Key="FormTextBox" TargetType="{x:Type TextBox}">
    <StackPanel>
        <TextBox x:Name="validableText"
                 MaxLength="{TemplateBinding MaxLength}"
                 Style="{StaticResource SectionEditPropertyTextBox}"
                 Text="{Binding RelativeSource={RelativeSource TemplatedParent},
                                Path=Text,
                                Mode=TwoWay,
                                UpdateSourceTrigger=PropertyChanged}" />
        <ContentPresenter Visibility="{Binding RelativeSource={RelativeSource TemplatedParent},
                                               Path=(Validation.HasError),
                                               Converter={StaticResource BooleanToVisibilityConverter}
                                               ConverterParameter=True}"
                            Content="{Binding RelativeSource={RelativeSource TemplatedParent},
                                              Path=(Validation.Errors).CurrentItem}"
                            HorizontalAlignment="Left">
            <ContentPresenter.ContentTemplate>
                <DataTemplate>
                    <Label Style="{StaticResource SectionEditErrorLabel}" Content="{Binding Path=ErrorContent}"/>
                </DataTemplate>
            </ContentPresenter.ContentTemplate>
        </ContentPresenter>
    </StackPanel>
</ControlTemplate>

在旁注中,您在此处拥有的另一个选择是使用您拥有的原始Xaml创建UserControl。您可以引入场景所需的依赖项属性(文本等)。它只需要很小的改动。