Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF: Validation.ErrorTemplate not displaying

I have a template for displaying a red border and an error message around controls. It works (tested on TextBoxes and ComboBoxes). But on two particular comboboxes they don't.
Well let's see what's different in the VM:

  • since I have common validation implementation in my base class, no change there
  • the same kind of asynchronously loaded data is displayed that works well with validation with just one panel over

so in short, no difference in VM.
The view is completely the same, the same style is applied, so in short no difference there either.

So I added NotifyOnValidationError=True to the ValidatesOnDataErrors=True already there, and subscribed to Validation.Error... And it fired!!! Yet the template still doesn't show. I'm out of ideas, please suggest me things to check!

EDIT: further research:

I've decompiled DataErrorValidationRule, and recompiled it as MyDataErrorValidationRule to match the original as close as possible. I removed ValidatesOnDataErrors=True, and added my ValidationRule to debug. It returned new ValidationResult(false, (object)str); with str containing the correct error message twice - once for setting the property to null, and once for forcefully validating the entire object. Template still not showing.

I've also checked Validation.GetErrorTemplate on the control (at the time of the first firing of Validation.Error) and it was NOT NULL, so it's not the DynamicResource that failed either.

EDIT: working example:

<ItemsControl ItemsSource="{Binding QuestionAnswers}">
                <ItemsControl.Resources>
                    <!-- ... -->
                    <DataTemplate DataType="{x:Type Model:QuestionAnswerModel}">
                        <StackPanel>
                                <!-- here is the combo box -->
                                <ComboBox Margin="8,4" Padding="8" MinWidth="120" HorizontalAlignment="Left" 
                                          Validation.ErrorTemplate="{DynamicResource DefaultValidationErrorTemplate}" 
                                          ItemsSource="{Binding Options.Source}"
                                          DisplayMemberPath="ItemName" SelectedValuePath="ItemID"
                                          SelectedValue="{Binding Options.SelectedID, ValidatesOnDataErrors=true}" />

                            </StackPanel>
                    </DataTemplate>
                </ItemsControl.Resources>
            </ItemsControl>

non-working example:

<ComboBox Margin="8,4" Padding="8" MinWidth="120" HorizontalAlignment="Left"
                          Validation.ErrorTemplate="{DynamicResource DefaultValidationErrorTemplate}"
                          SelectedItem="{Binding Type.SelectedItem, ValidatesOnDataErrors=True, NotifyOnValidationError=True}" Validation.Error="ComboBox_Error"
                          ItemsSource="{Binding Type.Source}"
                          DisplayMemberPath="Localized"
                          >

They are from the same xaml file, the ItemsControl containing the working ComboBox is in the same Grid as the non-working ComboBox.

The only difference is whether SelectedItem or SelectedValue is bound, but that shouldn't have any bearings on the validation...

like image 606
TDaver Avatar asked Nov 14 '22 04:11

TDaver


1 Answers

I had the exact problem with the error template not displaying even though the event was firiing, and could never figure out why it only happened for some controls and not others.

The workaround I eventually found was to set the ValidationStep to ConvertedProposedValue on the ValidationRule for the binding:

<TextBox>
  <TextBox.Text>
    <Binding Path="MyField">
      <Binding.ValidationRules>
        <Validation:MyValidationRule ValidationStep="ConvertedProposedValue" Message="Please enter a value." />
      </Binding.ValidationRules>
    </Binding>
  </TextBox.Text>
</TextBox>

That seemed to do the trick for me anyway!

EDIT: If you are using IDataErrorInfo, you could try (though I haven't personally tested it):

<Binding Path="MyField" ValidatesOnExceptions="True">
  <Binding.ValidationRules>
    <DataErrorValidationRule ValidationStep="ConvertedProposedValue" />
  </Binding.ValidationRules>
</Binding>

i.e. remove ValidatesOnDataErrors=True, which is just a shortcut for including a single <DataErrorValidationRule />

like image 130
Ross Avatar answered Dec 08 '22 08:12

Ross