Скрытие украшения проверки при скрытии элемента управления - PullRequest
4 голосов
/ 31 января 2011

Как в WPF скрыть украшение шаблона ошибки проверки (по умолчанию красное поле) при скрытии элемента управления? Когда я скрываю свои элементы управления (чтобы облегчить переключение между представлениями), украшение ошибки сохраняется.

Еще сложнее, как мне это сделать с помощью MVVM?

Ответы [ 2 ]

7 голосов
/ 01 февраля 2011

Значение по умолчанию ControlTemplate для Validation.ErrorTemplate имеет AdornedElementPlaceholder, что в свою очередь имеет ссылку на его AdornedElement. Похоже, это

<ControlTemplate>
    <Border BorderBrush="Red" BorderThickness="1">
        <AdornedElementPlaceholder />
    </Border>
</ControlTemplate>

Отсюда можно связать видимость Border с видимостью AdornedElementPlaceholder.AdornedElement, чтобы связать их видимость. Затем мы заставляем все Control, которые имеют эту проблему, использовать Validation.ErrorTemplate вместо значения по умолчанию. Вот пример

Xaml

<Window.Resources>
    <ControlTemplate x:Key="ValidationErrorTamplate">
        <Border Visibility="{Binding ElementName=placeHolder,
                                     Path=AdornedElement.Visibility}"
                BorderBrush="Red"
                BorderThickness="1">
            <AdornedElementPlaceholder x:Name="placeHolder"/>
        </Border>
    </ControlTemplate>
</Window.Resources>
<TextBox ...
         Validation.ErrorTemplate="{StaticResource ValidationErrorTamplate}">

Обновление
Для ссылки на родителя UserControl в привязке вы можете

1.Для конкретного элемента управления вы можете пройти по логическому дереву, используя свойство Parent

Пример : Если TextBox находится в StackPanel в UserControl, мы можем ссылаться на него с помощью Parent.Parent

<UserControl ...>
    <StackPanel>
        <TextBox ...
                 Validation.ErrorTemplate="{StaticResource ValidationErrorTamplate2}">

<ControlTemplate x:Key="ValidationErrorTamplate2">
    <Border Visibility="{Binding ElementName=placeHolder,
                                 Path=AdornedElement.Parent.Parent.Visibility}"
            BorderBrush="Red"
            BorderThickness="1">
        <AdornedElementPlaceholder x:Name="placeHolder"/>
    </Border>
</ControlTemplate>

2.Для более динамичного подхода вы можете использовать ResourceDictionary с файлом с кодом, где вы используете событие Loaded для Border. В нем вы поднимаетесь по визуальному дереву, чтобы найти родителя UserControl, и используете его в качестве источника для привязки

.

ValidationErrorTemplateDictionary.xaml

<ResourceDictionary x:Class="ValidationErrorVisibility.ValidationErrorTemplateDictionary"
                    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ControlTemplate x:Key="ValidationErrorTamplate3">
        <Border BorderBrush="Red"
                BorderThickness="1"
                Loaded="ValidationAdorner_Loaded">
            <AdornedElementPlaceholder/>
        </Border>
    </ControlTemplate>
</ResourceDictionary>

ValidationErrorTemplateDictionary.xaml.cs

public partial class ValidationErrorTemplateDictionary
{
    private void ValidationAdorner_Loaded(object sender, RoutedEventArgs e)
    {
        Border adornedBorder = sender as Border;
        Binding visibilityBinding = new Binding("Visibility");
        UIElement adornedElement = ((AdornedElementPlaceholder)adornedBorder.Child).AdornedElement;
        UserControl parentUserControl = GetVisualParent<UserControl>(adornedElement);
        visibilityBinding.Source = parentUserControl;
        adornedBorder.SetBinding(Border.VisibilityProperty, visibilityBinding);
    }

    public static T GetVisualParent<T>(object childObject) where T : Visual
    {
        DependencyObject child = childObject as DependencyObject;
        while ((child != null) && !(child is T))
        {
            child = VisualTreeHelper.GetParent(child);
        }
        return child as T;
    }
}

Ваш UserControl

<UserControl ...>
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="ValidationErrorTemplateDictionary.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>
    <StackPanel>
        <TextBox ...
                 Validation.ErrorTemplate="{StaticResource ValidationErrorTamplate3}">
0 голосов
/ 10 мая 2012

Мне только что пришлось решить эту проблему, для наглядности и непрозрачности.

Я сделал это, создав унаследованное вложенное свойство, с которым я связываю данные и прозрачность ErrorTemplate. На родительском элементе (фактический элемент, который постепенно исчезает / сворачивается), я просто связываю новые присоединенные свойства с видимостью и непрозрачностью соответственно.

Этот метод использует логическое дерево WPF и наследование существующего значения свойства для решения проблемы без кода или специальных знаний вашего шаблона о том, каким будет родитель, контролирующий видимость.

Оглядываясь назад, я мог бы создать одно прикрепленное свойство типа FrameWorkElement, которое затем я мог бы использовать для привязки к любому свойству родительского элемента. Этот подход будет включать меньше связывания и меньше кода для достижения при обеспечении немного большей гибкости. Возможно, прикрепленное свойство уже существует, чтобы позволить вам сделать то же самое.

Вы можете прочитать все о прикрепленных свойствах прямо здесь: http://msdn.microsoft.com/en-us/library/ms749011.aspx

Кроме того, это хороший стек: Как именно работают свойства Attached в WPF?

...