ValidatesOnDataError is used to validate business rules against your view models, and it will validate only if the binding succeeds.
ValidatesOnExceptions needs to be applied along with ValidatesOnDataError to handle those scenarios where wpf cannot perform binding because of data type mismatch, lets say you want to bind a TextBox to the Age (integer) property in your view model
<TextBox Text="{Binding Age, ValidatesOnDataErrors=true, UpdateSourceTrigger=PropertyChanged}" />
If the user enters invalid entry by typing alphabets rather than numbers as age, say xyz, the wpf databinding will silently ignores the value as it cannot bind xyz to Age, and the binding error will be lost unless the binding is decorated with ValidatesOnExceptions
<TextBox Text="{Binding Age, ValidatesOnDataErrors=true, ValidatesOnExceptions="True", UpdateSourceTrigger=PropertyChanged}" />
ValidatesOnException uses default exception handling for binding errors using ExceptionValidationRule, the above syntax is a short form for the following
<TextBox>
<TextBox.Text>
<Binding Path="Age" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True">
<Binding.ValidationRules>
<ExceptionValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
You can defined your own rules to validate against the user input by deriving from ValidationRule and implementing Validate method, NumericRule in the following example
<TextBox.Text>
<Binding Path="Age" ValidatesOnDataErrors="True">
<Binding.ValidationRules>
<rules:NumericRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
The validation rules should be generic and not tied to business, as the later is accomplished through IDataErrorInfo and ValidatesOnDataError.
The above syntax is quite messy compared to the one line binding syntax we have, by implementing the ValidationRule as an attached property the syntax can be improved and you can take a look at it here