By default, the ControlTemplate for Validation.ErrorTemplate has an AdornedElementPlaceholder , which in turn has a link to its AdornedElement . Looks like this
<ControlTemplate> <Border BorderBrush="Red" BorderThickness="1"> <AdornedElementPlaceholder /> </Border> </ControlTemplate>
From here, you can associate Border visibility with the AdornedElementPlaceholder.AdornedElement visibility to associate their visibility. Then we create all Control that have this problem using this Validation.ErrorTemplate instead of the standard one. Here is an example
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}">
Update
To reference the parent UserControl in the binding, you can
1. For a specific control, you can approach the logical tree using the Parent Property
An example . If the TextBox is in the StackPanel in the UserControl , we can reference it with 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.For a more dynamic approach, you can use ResourceDictionary with the code behind the file in which you use the Loaded event for Border . In it, you look at the visual tree to find the parent UserControl and use it as a binding source
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; } }
Your usercontrol
<UserControl ...> <UserControl.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="ValidationErrorTemplateDictionary.xaml"/> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </UserControl.Resources> <StackPanel> <TextBox ... Validation.ErrorTemplate="{StaticResource ValidationErrorTamplate3}">