From 55a0b5b1c633b4e1ea4b4b0aa248ad30691bfcfb Mon Sep 17 00:00:00 2001 From: Tim <47110241+timunie@users.noreply.github.com> Date: Wed, 26 Nov 2025 18:03:14 +0100 Subject: [PATCH] feat: Handle Datavalidations on base class "Control" (#20067) * Handle Datavalidations on base class "Control" this removes the need to override it in any sub-classing control and also allowes developers to add validation support for other properties / controls by overriding Metadata * Revert changes on Button. The current behavior is that button gets disabled and until we decide if this is desired, keep this behavior. --- .../AutoCompleteBox/AutoCompleteBox.cs | 18 ------------------ src/Avalonia.Controls/Button.cs | 3 ++- .../CalendarDatePicker/CalendarDatePicker.cs | 11 ----------- src/Avalonia.Controls/Control.cs | 8 ++++++++ .../DateTimePickers/DatePicker.cs | 8 -------- .../DateTimePickers/TimePicker.cs | 8 -------- src/Avalonia.Controls/MenuItem.cs | 1 + .../NumericUpDown/NumericUpDown.cs | 18 ------------------ .../Primitives/SelectingItemsControl.cs | 18 ------------------ src/Avalonia.Controls/Slider.cs | 12 ------------ src/Avalonia.Controls/TextBox.cs | 11 ----------- 11 files changed, 11 insertions(+), 105 deletions(-) diff --git a/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs b/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs index f61f6ff2a1..d2fa2bea2b 100644 --- a/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs +++ b/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs @@ -652,24 +652,6 @@ namespace Avalonia.Controls base.OnApplyTemplate(e); } - /// - /// Called to update the validation state for properties for which data validation is - /// enabled. - /// - /// The property. - /// The current data binding state. - /// The current data binding error, if any. - protected override void UpdateDataValidation( - AvaloniaProperty property, - BindingValueType state, - Exception? error) - { - if (property == TextProperty || property == SelectedItemProperty) - { - DataValidationErrors.SetError(this, error); - } - } - /// /// Provides handling for the /// event. diff --git a/src/Avalonia.Controls/Button.cs b/src/Avalonia.Controls/Button.cs index 12c778bf2e..3652acac45 100644 --- a/src/Avalonia.Controls/Button.cs +++ b/src/Avalonia.Controls/Button.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using System.Linq; using System.Windows.Input; using Avalonia.Automation.Peers; @@ -571,7 +572,7 @@ namespace Avalonia.Controls } } } - + internal void PerformClick() => OnClick(); private static void OnAccessKeyPressed(Button sender, AccessKeyPressedEventArgs e) diff --git a/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs b/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs index eaf632039b..e3ce49ac96 100644 --- a/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs +++ b/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs @@ -325,17 +325,6 @@ namespace Avalonia.Controls base.OnPropertyChanged(change); } - /// - protected override void UpdateDataValidation(AvaloniaProperty property, BindingValueType state, Exception? error) - { - if (property == SelectedDateProperty) - { - DataValidationErrors.SetError(this, error); - } - - base.UpdateDataValidation(property, state, error); - } - /// protected override void OnPointerPressed(PointerPressedEventArgs e) { diff --git a/src/Avalonia.Controls/Control.cs b/src/Avalonia.Controls/Control.cs index 4f3e76d487..b5f3ba57ce 100644 --- a/src/Avalonia.Controls/Control.cs +++ b/src/Avalonia.Controls/Control.cs @@ -4,6 +4,7 @@ using System.ComponentModel; using Avalonia.Automation.Peers; using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; +using Avalonia.Data; using Avalonia.Input; using Avalonia.Input.Platform; using Avalonia.Interactivity; @@ -563,6 +564,13 @@ namespace Avalonia.Controls } } } + + /// + protected override void UpdateDataValidation(AvaloniaProperty property, BindingValueType state, Exception? error) + { + DataValidationErrors.SetError(this, error); + base.UpdateDataValidation(property, state, error); + } // Since we are resetting the dispatcher instance, the callback might never arrive internal static void ResetLoadedQueueForUnitTests() diff --git a/src/Avalonia.Controls/DateTimePickers/DatePicker.cs b/src/Avalonia.Controls/DateTimePickers/DatePicker.cs index ac2ca3db8b..2f88e662a2 100644 --- a/src/Avalonia.Controls/DateTimePickers/DatePicker.cs +++ b/src/Avalonia.Controls/DateTimePickers/DatePicker.cs @@ -426,13 +426,5 @@ namespace Avalonia.Controls { SetCurrentValue(SelectedDateProperty, null); } - - protected override void UpdateDataValidation(AvaloniaProperty property, BindingValueType state, Exception? error) - { - base.UpdateDataValidation(property, state, error); - - if (property == SelectedDateProperty) - DataValidationErrors.SetError(this, error); - } } } diff --git a/src/Avalonia.Controls/DateTimePickers/TimePicker.cs b/src/Avalonia.Controls/DateTimePickers/TimePicker.cs index c9e62e2cb2..ca5c43463d 100644 --- a/src/Avalonia.Controls/DateTimePickers/TimePicker.cs +++ b/src/Avalonia.Controls/DateTimePickers/TimePicker.cs @@ -407,13 +407,5 @@ namespace Avalonia.Controls { SetCurrentValue(SelectedTimeProperty, null); } - - protected override void UpdateDataValidation(AvaloniaProperty property, BindingValueType state, Exception? error) - { - base.UpdateDataValidation(property, state, error); - - if (property == SelectedTimeProperty) - DataValidationErrors.SetError(this, error); - } } } diff --git a/src/Avalonia.Controls/MenuItem.cs b/src/Avalonia.Controls/MenuItem.cs index f250f8da43..54bae5b891 100644 --- a/src/Avalonia.Controls/MenuItem.cs +++ b/src/Avalonia.Controls/MenuItem.cs @@ -554,6 +554,7 @@ namespace Avalonia.Controls return new MenuItemAutomationPeer(this); } + // TODO: This is confusing for some ppl. Need to think about alternatives here. protected override void UpdateDataValidation( AvaloniaProperty property, BindingValueType state, diff --git a/src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs b/src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs index 90cfb41c65..d9cc92f0e6 100644 --- a/src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs +++ b/src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs @@ -441,24 +441,6 @@ namespace Avalonia.Controls } } - /// - /// Called to update the validation state for properties for which data validation is - /// enabled. - /// - /// The property. - /// The current data binding state. - /// The current data binding error, if any. - protected override void UpdateDataValidation( - AvaloniaProperty property, - BindingValueType state, - Exception? error) - { - if (property == TextProperty || property == ValueProperty) - { - DataValidationErrors.SetError(this, error); - } - } - /// /// Called when the property value changed. /// diff --git a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs index 59289838bb..b1b7ae7f4e 100644 --- a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs +++ b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs @@ -569,24 +569,6 @@ namespace Avalonia.Controls.Primitives EndUpdating(); } - /// - /// Called to update the validation state for properties for which data validation is - /// enabled. - /// - /// The property. - /// The current data binding state. - /// The current data binding error, if any. - protected override void UpdateDataValidation( - AvaloniaProperty property, - BindingValueType state, - Exception? error) - { - if (property == SelectedItemProperty) - { - DataValidationErrors.SetError(this, error); - } - } - /// protected override void OnInitialized() { diff --git a/src/Avalonia.Controls/Slider.cs b/src/Avalonia.Controls/Slider.cs index 4d34bd354e..2984e191b1 100644 --- a/src/Avalonia.Controls/Slider.cs +++ b/src/Avalonia.Controls/Slider.cs @@ -393,18 +393,6 @@ namespace Avalonia.Controls SetCurrentValue(ValueProperty, IsSnapToTickEnabled ? SnapToTick(finalValue) : finalValue); } - /// - protected override void UpdateDataValidation( - AvaloniaProperty property, - BindingValueType state, - Exception? error) - { - if (property == ValueProperty) - { - DataValidationErrors.SetError(this, error); - } - } - protected override AutomationPeer OnCreateAutomationPeer() { return new SliderAutomationPeer(this); diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index 35f1c34b5e..33cfddc4a1 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -1884,17 +1884,6 @@ namespace Avalonia.Controls return new TextBoxAutomationPeer(this); } - protected override void UpdateDataValidation( - AvaloniaProperty property, - BindingValueType state, - Exception? error) - { - if (property == TextProperty) - { - DataValidationErrors.SetError(this, error); - } - } - internal static int CoerceCaretIndex(AvaloniaObject sender, int value) { var text = sender.GetValue(TextProperty); // method also used by TextPresenter and SelectableTextBlock