I have an issue very similar to these:
Issue with WPF validation(IDataErrorInfo) and tab focusing
TextBox with validation loses ErrorTemplate on tab change
AdornerDecorator do the trick within the same instance of the Window, but when the Window is reloaded and I switch to the TabItem containing the TextBox in error, the ErrorTemplate won't show up anymore.
<Window x:Class="Views.MyWindowView">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TabControl HorizontalAlignment="Stretch"
Height="Auto"
VerticalAlignment="Top"
Width="Auto"
SelectionChanged="TabItemChanged"
Name="MyTabControl">
<!-- Below, AdornerDecorator are added for the following reason:
the Validation.Error cues are painted in the Adorner Layer.
When tabs are switched, that layer is discarded. -->
<!-- The view 1 tab.-->
<TabItem Header="{Resx tab1_Header}"
Name="Tbi1">
<AdornerDecorator>
<vw:MyView1 DataContext="{Binding}"/>
</AdornerDecorator>
</TabItem>
<!-- The view 2 tab.-->
<TabItem Header="{Resx tab2_Header}"
Name="Tbi2">
<AdornerDecorator>
<vw:MyView2 DataContext="{Binding}"/>
</AdornerDecorator>
</TabItem>
</TabControl>
...
I tried to retrigger the validation in the code-behind on TabControl SelectionChanged, didn't work.
Any idea?
Putting together the pieces of the puzzle
An AdornerLayer represents a surface for rendering adorners. As an
AdornerLayerusually serves an entire view, not just one control, some containers implement them by default.An adorner is a custom
FrameworkElementthat is bound to aUIElement. Adorners are rendered in anAdornerLayer, which is a rendering surface that is always on top of the adorned element or a collection of adorned elements.So in this case the adorner (red rectangle) is bound to a
TextBox, but is rendered in a layer on top of theTextBox.Adorning (e.g. in case of a validation error) is done by calling the static method
GetAdornerLayerto get anAdornerLayerobject for theUIElementto be adorned.Enough theory
Changing
TabItemsdiscards theAdornerLayer, resulting in the adorner not being drawn. 2 fixes:\The manual way, as proposed by DRapp:
Of course, if there's another container implementing an
AdornerLayerbetween theAdornerDecoratorand theTextBox(in the visual tree), this won't do any good. So the explicitAdornerDecoratorneeds to be the last one wrapping theTextBox.\Second solution (which I prefer) resetting the ErrorTemplate each time the
TextBoxbecomes visible. In doing so the lack ofAdornerLayergets spotted and fixed.