Repository: AvaloniaUI/Avalonia

Issue:
Regression: Exceptions thrown in TargetTypeConverter crash the app instead of going to the controls DataValidation
### Describe the bug

Exceptions thrown in TargetTypeConverter crash the whole app, instead of being caught into control's Data Validation.

### To Reproduce

```
<TextBox Text="{CompiledBinding Value}" />
```
where Value is an `int` - and type a letter.

```
Unhandled exception. System.ArgumentException: 0a is not a valid value for Int32. (Parameter 'value')
 ---> System.FormatException: The input string '0a' was not in a correct format.
   at System.Number.ThrowFormatException[TChar](ReadOnlySpan`1 value)
   at System.Int32.Parse(String s, NumberStyles style, IFormatProvider provider)
   at System.ComponentModel.Int32Converter.FromString(String value, NumberFormatInfo formatInfo)
   at System.ComponentModel.BaseNumberConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
   --- End of inner exception stack trace ---
   at System.ComponentModel.BaseNumberConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
   at Avalonia.Data.Core.TargetTypeConverter.DefaultConverter.TryConvert(Object value, Type type, CultureInfo culture, Object& result)
   at Avalonia.Data.Core.BindingExpression.WriteValueToSource(Object value)
   at Avalonia.Data.Core.BindingExpression.OnTargetPropertyChanged(Object sender, AvaloniaPropertyChangedEventArgs e)
   at Avalonia.AvaloniaObject.RaisePropertyChanged[T](AvaloniaProperty`1 property, Optional`1 oldValue, BindingValue`1 newValue, BindingPriority priority, Boolean isEffectiveValue)
   at Avalonia.PropertyStore.EffectiveValue`1.SetAndRaiseCore(ValueStore owner, StyledProperty`1 property, T value, BindingPriority priority, Boolean isOverriddenCurrentValue, Boolean isCoercedDefaultValue)
   at Avalonia.PropertyStore.EffectiveValue`1.SetCurrentValueAndRaise(ValueStore owner, StyledProperty`1 property, T value)
   at Avalonia.PropertyStore.ValueStore.SetCurrentValue[T](StyledProperty`1 property, T value)
   at Avalonia.AvaloniaObject.SetCurrentValue[T](StyledProperty`1 property, T value)
   at Avalonia.Controls.TextBox.HandleTextInput(String input)
   at Avalonia.Controls.TextBox.OnTextInput(TextInputEventArgs e)
   at Avalonia.Input.InputElement.<>c.<.cctor>b__32_4(InputElement x, TextInputEventArgs e)
   at Avalonia.Reactive.LightweightObservableBase`1.PublishNext(T value)
   at Avalonia.Interactivity.RoutedEvent.InvokeRaised(Object sender, RoutedEventArgs e)
   at Avalonia.Interactivity.EventRoute.RaiseEventImpl(RoutedEventArgs e)
   at Avalonia.Interactivity.EventRoute.RaiseEvent(Interactive source, RoutedEventArgs e)
   at Avalonia.Interactivity.Interactive.RaiseEvent(RoutedEventArgs e)
   at Avalonia.Input.KeyboardDevice.ProcessRawEvent(RawInputEventArgs e)
   at Avalonia.Input.InputManager.ProcessInput(RawInputEventArgs e)
   at Avalonia.Controls.TopLevel.<>c.<HandleInput>b__141_0(Object state)
   at Avalonia.Threading.Dispatcher.Send(SendOrPostCallback action, Object arg, Nullable`1 priority)
   at Avalonia.Controls.TopLevel.HandleInput(RawInputEventArgs e)
   at Avalonia.Native.WindowBaseImpl.RawTextInputEvent(UInt64 timeStamp, String text)
   at Avalonia.Native.WindowBaseImpl.WindowBaseEvents.Avalonia.Native.Interop.IAvnWindowBaseEvents.RawTextInputEvent(UInt64 timeStamp, String text)
   at Avalonia.Native.Interop.Impl.__MicroComIAvnWindowBaseEventsVTable.RawTextInputEvent(Void* this, UInt64 timeStamp, Byte* text)
--- End of stack trace from previous location ---
   at Avalonia.Native.DispatcherImpl.RunLoop(CancellationToken token)
   at Avalonia.Threading.DispatcherFrame.Run(IControlledDispatcherImpl impl)
   at Avalonia.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at Avalonia.Threading.Dispatcher.MainLoop(CancellationToken cancellationToken)
   at Avalonia.Controls.ApplicationLifetimes.ClassicDesktopStyleApplicationLifetime.Start(String[] args)
   at Avalonia.ClassicDesktopStyleApplicationLifetimeExtensions.StartWithClassicDesktopLifetime(AppBuilder builder, String[] args, Action`1 lifetimeBuilder)
   at AvaloniaBugs.Program.Main(String[] args) in /AvaloniaBugsAll/bug_type_converter/AvaloniaBugs/Program.cs:line 12
```

or

1. `git clone https://github.com/BAndysc/avalonia-bugs-repro`
2. `git checkout bug_type_converter`
3. Run and type a letter

### Expected behavior

No crash, like before binding refactor.

### Avalonia version

11.1-beta

### OS

_No response_

### Additional context

_No response_


Hints:

Patch:
diff --git a/src/Avalonia.Base/Data/Core/TargetTypeConverter.cs b/src/Avalonia.Base/Data/Core/TargetTypeConverter.cs
index 2efc5b42bdc..57018bff55e 100644
--- a/src/Avalonia.Base/Data/Core/TargetTypeConverter.cs
+++ b/src/Avalonia.Base/Data/Core/TargetTypeConverter.cs
@@ -76,16 +76,32 @@ public override bool TryConvert(object? value, Type type, CultureInfo culture, o
 
             if (toTypeConverter.CanConvertFrom(from))
             {
-                result = toTypeConverter.ConvertFrom(null, culture, value);
-                return true;
+                try
+                {
+                    result = toTypeConverter.ConvertFrom(null, culture, value);
+                    return true;
+                }
+                catch
+                {
+                    result = null;
+                    return false;
+                }
             }
 
             var fromTypeConverter = TypeDescriptor.GetConverter(from);
 
             if (fromTypeConverter.CanConvertTo(t))
             {
-                result = fromTypeConverter.ConvertTo(null, culture, value, t);
-                return true;
+                try
+                {
+                    result = fromTypeConverter.ConvertTo(null, culture, value, t);
+                    return true;
+                }
+                catch
+                {
+                    result = null;
+                    return false;
+                }
             }
 
             // TODO: This requires reflection: we probably need to make compiled bindings emit
@@ -95,8 +111,16 @@ public override bool TryConvert(object? value, Type type, CultureInfo culture, o
                 t,
                 OperatorType.Implicit | OperatorType.Explicit) is { } cast)
             {
-                result = cast.Invoke(null, new[] { value });
-                return true;
+                try
+                {
+                    result = cast.Invoke(null, new[] { value });
+                    return true;
+                }
+                catch
+                {
+                    result = null;
+                    return false;
+                }
             }
 #pragma warning restore IL2067
 #pragma warning restore IL2026


Test patch:
diff --git a/tests/Avalonia.Controls.UnitTests/TextBoxTests_DataValidation.cs b/tests/Avalonia.Controls.UnitTests/TextBoxTests_DataValidation.cs
index 295fc192d76..0eaa3092e98 100644
--- a/tests/Avalonia.Controls.UnitTests/TextBoxTests_DataValidation.cs
+++ b/tests/Avalonia.Controls.UnitTests/TextBoxTests_DataValidation.cs
@@ -6,8 +6,11 @@
 using Avalonia.Controls.Presenters;
 using Avalonia.Controls.Templates;
 using Avalonia.Data;
+using Avalonia.Data.Core;
 using Avalonia.Headless;
 using Avalonia.Markup.Data;
+using Avalonia.Markup.Xaml.MarkupExtensions;
+using Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings;
 using Avalonia.Platform;
 using Avalonia.UnitTests;
 using Moq;
@@ -110,6 +113,40 @@ public void Setter_Exceptions_Should_Set_DataValidationErrors_HasErrors()
             }
         }
 
+        [Fact]
+        public void CompiledBindings_TypeConverter_Exceptions_Should_Set_DataValidationErrors_HasErrors()
+        {
+            var path = new CompiledBindingPathBuilder()
+            .Property(
+                new ClrPropertyInfo(
+                    nameof(ExceptionTest.LessThan10),
+                    target => ((ExceptionTest)target).LessThan10,
+                    (target, value) => ((ExceptionTest)target).LessThan10 = (int)value,
+                    typeof(int)),
+                PropertyInfoAccessorFactory.CreateInpcPropertyAccessor)
+            .Build();
+
+            using (UnitTestApplication.Start(Services))
+            {
+                var target = new TextBox
+                {
+                    DataContext = new ExceptionTest(),
+                    [!TextBox.TextProperty] = new CompiledBindingExtension
+                    {
+                        Source = new ExceptionTest(),
+                        Path = path,
+                        Mode = BindingMode.TwoWay
+                    },
+                    Template = CreateTemplate(),
+                };
+
+                target.ApplyTemplate();
+
+                target.Text = "a";
+                Assert.True(DataValidationErrors.GetHasErrors(target));
+            }
+        }
+
         private static TestServices Services => TestServices.MockThreadingInterface.With(
             standardCursorFactory: Mock.Of<ICursorFactory>(),
             textShaperImpl: new HeadlessTextShaperStub(),