WPF Вложенное связывание в шаблоне управления - PullRequest
4 голосов
/ 18 августа 2011

Я успешно создал текстовое поле, которое отображает / сворачивает сообщение об ошибке в зависимости от правила проверки, установленного в его модели / vm. Код идет так для электронной почты для ex.:

    <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 Ответ

5 голосов
/ 18 августа 2011

Вам не понадобятся привязки Grid.Row и Grid.Column в шаблоне StackPanel, поскольку StackPanel в любом случае не будет прямым потомком Grid,

TemplateBinding всегда является привязкой OneWay, поэтому свойство Text для Templated TextBox никогда не будет обновлено. Измените его на обычную привязку с RelativeSource и TwoWay

Измените ElementName=validableText на RelativeSource={RelativeSource TemplatedParent} в привязках для 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>

Кстати, еще одна альтернатива, которую вы здесь имеете, - создать UserControl с исходным фрагментом Xaml, который у вас был. Вы можете ввести свойства зависимости, необходимые для вашего сценария (текст и т. Д.). Это потребует только небольших изменений.

...