24

This is a bit of a WPF whodunnit! My validation temples it not appearing when expected

The Problem

Basically, I am using IDataErrorInfo on my view model to provide feedback on data entry errors. I can see this being called and working as expected, but the validation error template for the bound control is never displayed by WPF!

I have tried both using the built-in default textbox red border error template, a style error template, and a hard coded template. None of these are displayed in a data error situation.

Heres my xaml binding code:

<TextBox x:Name="txtCaseNumber"  
Text="{Binding Path=CaseNumber, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"/>

Wierdly, the error gets into the Validation.Errors collection. The follow code results in my IDataErrorInfo error message getting displayed next to the bound control. This leads me to think the problem is on the xaml side, rather the viewmodel side.

<ContentPresenter 
Content="{Binding ElementName=txtCaseNumber, Path=(Validation.Errors).CurrentItem}" />

Additionally, System.Windows.Controls.Validation.GetHasError(txtCaseNumber) returns true.

I am hosting WPF in winforms if that makes a difference. I can't find any references in my code or styles to Validation or ErrorTemplate so I'm pretty sure this isn't a styling own goal.

Noel Kennedy
  • 12,128
  • 3
  • 40
  • 57

1 Answers1

50

Cracked it.

The ErrorTemplate attached property uses the adorner layer to show error templates on data validation failures reported via IDataErrorInfo. The Adorner layer is not always available for all controls in all situations. Your control or one of its parents needs to explicitly provide one.

The default Window control template contains an AdornerDecorator which enables the adorner layer for its children. This why my other window showed my error templates just fine, because this window used the default control template

The window which didn't show my error template had used a style which provided a ControlTemplate for my window. This control template did not provide an <AdornerDecorator>, hence no adorner layer to show my error template.

The fix was as simple as wrapping my window control template with <AdornerDecorator>.

Noel Kennedy
  • 12,128
  • 3
  • 40
  • 57
  • 5
    I tip my hat to you, Sir! I had a UserControl > Expander > Textbox in a VS Extension. But it wouldn't show the IDataErrorInfo errors. Made a sample WPF app to host the UC - issue persisted (VS Extn ruled out). Made another VM - that worked ruled out the VM. Then I hit your post - added a couple of Loaded event handlers to the window and the UC. Sure enough, UC returned a null AdornerLayer. Wrapped the expander content with AdornerDecorator and it worked! Slowed me down by 2 days.. live n learn I guess. Once again, thanks for the persistence and time to document it for posterity!! – Gishu Oct 14 '10 at 18:03
  • 2
    This just fixed my issue with a Metro-style window that didn't provide an AdornerDecorator. Thanks! – mortware Aug 06 '12 at 15:51
  • This solves the same problem while using the ModernDialog of Modern UI. If you wrap the content of ModernDialog with an AdornerDecorator the problem is fixed. Thank you very much. – Huseyin Yagli Mar 18 '16 at 08:31
  • Same problem, though it took me a while to figure out the correct place for the AdornerDecorator. Unlike for Gishu the AdornerDecorator on the expander content did not worl. In my case the tree is something like Window > Expander > StackPanel > StackPanel > TextBox and the AdornerDecorator had to be around that last StackPanel. – stijn Aug 12 '18 at 10:48