Значение по умолчанию 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}">