Description
Describe the bug
When using Bindings to synchronize DataValidationErrors.Errors
for one control with the DataValidationErrors.Errors
property of another control, the secondary control's DataValidationErrors.HasErrors
property does not get updated correctly.
To Reproduce
This is most easily observed in the AutoComlpeteBox control. The control uses a child TextBox control, and in the theme file, the TextBox uses this line to synchronize its Errors property: DataValidationErrors.Errors="{TemplateBinding (DataValidationErrors.Errors)}"
When the parent AutoCompleteBox's Errors property gets updated, the child TextBox does have its Errors synchronized, however its HasErrors property remains false even though the property is true for the parent control. (You can easily see this with the F12 DevTools, looking at the DataValidationErrors
properties for the child TextBox)
NOTE: I have also included the AutoCompleteBoxTest project in my fork of Avalonia here: https://github.com/drone1400/Avalonia/tree/temp/drone-samples-autocompletebox-test
I have attached a simple application with both an AutoCompleteBox and second TextBox control with both of their Text properties bound to the same string property in the view model. When the string property change triggers a Validation update, the stand-alone TextBox control displays the validation error message correctly, while the AutoCompleteBox does not.
NOTE: The AutoCompleteBox does display the validation error message upon first initialization, but not subsequent updates.
Expected behavior
The inner TextBox control of the AutoCompleteBox should have its DataValidationErrors.HasErrors
property updated when its DataValidationErrors.Errors
property is updated using Bindings.
Avalonia version
11.2.7
OS
Windows
Additional context
I actually looked into why this was happening and found a fix for it before submitting this issue. I will be submitting a PR as well for it, but here is an explanation.
The issue is located in the Avalonia.Controls project, in the DataValidationErrors.cs file.
The root of the issue seems to be that the DataValidationErrors uses the private static bool s_overridingErrors
field to temporarily inhibit the ErrorsChanged
handler after updating the Errors
property internally in OnErrorsOrConverterChanged
While this is usually fine, when using bindings, the 2nd control's ErrorsChanged
handler gets called before s_overridingErrors
has a chance to be cleared and thus no longer gets executed.
In the case of the AutoCompleteBox, after changing its Errors property, upon entering the handler private static void ErrorsChanged(AvaloniaPropertyChangedEventArgs e)
, the e.Sender
and s_overridingErrors
properties end up having the following values:
e.Sender | s_overridingErrors | |
---|---|---|
1 | AutoCompleteBox | false |
2 | AutoCompleteBox | true |
3 | PART_TextBox | true |
4 | AutoCompleteBox | false |
5 | AutoCompleteBox | true |
6 | PART_TextBox | true |
When the handler gets executed for the child TextBox, the s_overridingErrors
property is true each time and nothing gets executed.
As I mentioned above, I will be submitting a PR with my fix for this issue momentarily.