Hide binding plugins and disable Data Annotations validation by default (#20623)
* Make binding plugin API internal. Making everything pluggable like has performance implications even if the plugins are never customized (which will be the 99% case). `IPropertyAccessor` is used in `CompiledBindingPathBuilder` so needs to be kept public for the moment. * Disable Data Annotations validation by default. It [conflicts with `CommunityToolkit.Mvvm`](https://github.com/AvaloniaUI/Avalonia/issues/8397) which is now the default MVVM framework, so require it to be enabled in the `AppBuilder`. * Update API supressions. * Add back missing using --------- Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
This commit is contained in:
@@ -25,6 +25,60 @@
|
||||
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0001</DiagnosticId>
|
||||
<Target>T:Avalonia.Data.Core.Plugins.BindingPlugins</Target>
|
||||
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0001</DiagnosticId>
|
||||
<Target>T:Avalonia.Data.Core.Plugins.DataValidationBase</Target>
|
||||
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0001</DiagnosticId>
|
||||
<Target>T:Avalonia.Data.Core.Plugins.ExceptionValidationPlugin</Target>
|
||||
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0001</DiagnosticId>
|
||||
<Target>T:Avalonia.Data.Core.Plugins.IDataValidationPlugin</Target>
|
||||
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0001</DiagnosticId>
|
||||
<Target>T:Avalonia.Data.Core.Plugins.IndeiValidationPlugin</Target>
|
||||
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0001</DiagnosticId>
|
||||
<Target>T:Avalonia.Data.Core.Plugins.IPropertyAccessorPlugin</Target>
|
||||
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0001</DiagnosticId>
|
||||
<Target>T:Avalonia.Data.Core.Plugins.IStreamPlugin</Target>
|
||||
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0001</DiagnosticId>
|
||||
<Target>T:Avalonia.Data.Core.Plugins.PropertyAccessorBase</Target>
|
||||
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0001</DiagnosticId>
|
||||
<Target>T:Avalonia.Data.Core.Plugins.PropertyError</Target>
|
||||
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0001</DiagnosticId>
|
||||
<Target>T:Avalonia.Diagnostics.AppliedStyle</Target>
|
||||
@@ -253,6 +307,60 @@
|
||||
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0001</DiagnosticId>
|
||||
<Target>T:Avalonia.Data.Core.Plugins.BindingPlugins</Target>
|
||||
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0001</DiagnosticId>
|
||||
<Target>T:Avalonia.Data.Core.Plugins.DataValidationBase</Target>
|
||||
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0001</DiagnosticId>
|
||||
<Target>T:Avalonia.Data.Core.Plugins.ExceptionValidationPlugin</Target>
|
||||
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0001</DiagnosticId>
|
||||
<Target>T:Avalonia.Data.Core.Plugins.IDataValidationPlugin</Target>
|
||||
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0001</DiagnosticId>
|
||||
<Target>T:Avalonia.Data.Core.Plugins.IndeiValidationPlugin</Target>
|
||||
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0001</DiagnosticId>
|
||||
<Target>T:Avalonia.Data.Core.Plugins.IPropertyAccessorPlugin</Target>
|
||||
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0001</DiagnosticId>
|
||||
<Target>T:Avalonia.Data.Core.Plugins.IStreamPlugin</Target>
|
||||
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0001</DiagnosticId>
|
||||
<Target>T:Avalonia.Data.Core.Plugins.PropertyAccessorBase</Target>
|
||||
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0001</DiagnosticId>
|
||||
<Target>T:Avalonia.Data.Core.Plugins.PropertyError</Target>
|
||||
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0001</DiagnosticId>
|
||||
<Target>T:Avalonia.Diagnostics.AppliedStyle</Target>
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Avalonia.Data.Core.Plugins
|
||||
/// Holds a registry of plugins used for bindings.
|
||||
/// </summary>
|
||||
[RequiresUnreferencedCode(TrimmingMessages.PropertyAccessorsRequiresUnreferencedCodeMessage)]
|
||||
public static class BindingPlugins
|
||||
internal static class BindingPlugins
|
||||
{
|
||||
internal static readonly List<IPropertyAccessorPlugin> s_propertyAccessors = new()
|
||||
{
|
||||
@@ -17,7 +17,6 @@ namespace Avalonia.Data.Core.Plugins
|
||||
|
||||
internal static readonly List<IDataValidationPlugin> s_dataValidators = new()
|
||||
{
|
||||
new DataAnnotationsValidationPlugin(),
|
||||
new IndeiValidationPlugin(),
|
||||
new ExceptionValidationPlugin(),
|
||||
};
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Avalonia.Data.Core.Plugins
|
||||
/// and convert any values received from the inner property accessor into
|
||||
/// <see cref="BindingNotification"/>s.
|
||||
/// </remarks>
|
||||
public abstract class DataValidationBase : PropertyAccessorBase, IObserver<object?>
|
||||
internal abstract class DataValidationBase : PropertyAccessorBase, IObserver<object?>
|
||||
{
|
||||
private readonly IPropertyAccessor _inner;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Avalonia.Data.Core.Plugins
|
||||
/// <summary>
|
||||
/// Validates properties that report errors by throwing exceptions.
|
||||
/// </summary>
|
||||
public class ExceptionValidationPlugin : IDataValidationPlugin
|
||||
internal class ExceptionValidationPlugin : IDataValidationPlugin
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public bool Match(WeakReference<object?> reference, string memberName) => true;
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Avalonia.Data.Core.Plugins
|
||||
/// <summary>
|
||||
/// Defines how data validation is observed by an <see cref="BindingExpression"/>.
|
||||
/// </summary>
|
||||
public interface IDataValidationPlugin
|
||||
internal interface IDataValidationPlugin
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks whether this plugin can handle data validation on the specified object.
|
||||
|
||||
@@ -3,8 +3,7 @@ using System;
|
||||
namespace Avalonia.Data.Core.Plugins
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines an accessor to a property on an object returned by a
|
||||
/// <see cref="IPropertyAccessorPlugin"/>
|
||||
/// Defines an accessor to a property on an object.
|
||||
/// </summary>
|
||||
public interface IPropertyAccessor : IDisposable
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Avalonia.Data.Core.Plugins
|
||||
/// <summary>
|
||||
/// Defines how a member is read, written and observed by a binding.
|
||||
/// </summary>
|
||||
public interface IPropertyAccessorPlugin
|
||||
internal interface IPropertyAccessorPlugin
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks whether this plugin can handle accessing the properties of the specified object.
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Avalonia.Data.Core.Plugins
|
||||
/// <summary>
|
||||
/// Defines a plugin that handles the '^' stream binding operator.
|
||||
/// </summary>
|
||||
public interface IStreamPlugin
|
||||
internal interface IStreamPlugin
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks whether this plugin handles the specified value.
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Avalonia.Data.Core.Plugins
|
||||
/// <summary>
|
||||
/// Validates properties on objects that implement <see cref="INotifyDataErrorInfo"/>.
|
||||
/// </summary>
|
||||
public class IndeiValidationPlugin : IDataValidationPlugin
|
||||
internal class IndeiValidationPlugin : IDataValidationPlugin
|
||||
{
|
||||
private static readonly WeakEvent<INotifyDataErrorInfo, DataErrorsChangedEventArgs>
|
||||
ErrorsChangedWeakEvent = WeakEvent.Register<INotifyDataErrorInfo, DataErrorsChangedEventArgs>(
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Avalonia.Data.Core.Plugins
|
||||
/// <summary>
|
||||
/// Defines a default base implementation for a <see cref="IPropertyAccessor"/>.
|
||||
/// </summary>
|
||||
public abstract class PropertyAccessorBase : IPropertyAccessor
|
||||
internal abstract class PropertyAccessorBase : IPropertyAccessor
|
||||
{
|
||||
private Action<object?>? _listener;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Avalonia.Data.Core.Plugins
|
||||
/// <summary>
|
||||
/// An <see cref="IPropertyAccessor"/> that represents an error.
|
||||
/// </summary>
|
||||
public class PropertyError : IPropertyAccessor
|
||||
internal class PropertyError : IPropertyAccessor
|
||||
{
|
||||
private readonly BindingNotification _error;
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Metadata;
|
||||
using Avalonia.Data.Core.Plugins;
|
||||
|
||||
namespace Avalonia
|
||||
{
|
||||
@@ -265,6 +267,17 @@ namespace Avalonia
|
||||
return Self;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds support for validation using <c>System.ComponentModel.DataAnnotations</c>.
|
||||
/// </summary>
|
||||
[RequiresUnreferencedCode(TrimmingMessages.PropertyAccessorsRequiresUnreferencedCodeMessage)]
|
||||
public AppBuilder WithDataAnnotationsValidation()
|
||||
{
|
||||
if (!BindingPlugins.DataValidators.Any(x => x is DataAnnotationsValidationPlugin))
|
||||
BindingPlugins.DataValidators.Insert(0, new DataAnnotationsValidationPlugin());
|
||||
return Self;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers an action that is executed with the current font manager.
|
||||
/// </summary>
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Data.Core.Plugins;
|
||||
using Avalonia.UnitTests;
|
||||
using Xunit;
|
||||
|
||||
@@ -273,6 +275,9 @@ public partial class BindingExpressionTests
|
||||
[Fact]
|
||||
public void Updates_Data_Validation_For_Required_DataAnnotation()
|
||||
{
|
||||
if (!BindingPlugins.DataValidators.Any(x => x is DataAnnotationsValidationPlugin))
|
||||
BindingPlugins.DataValidators.Insert(0, new DataAnnotationsValidationPlugin());
|
||||
|
||||
var data = new DataAnnotationsViewModel();
|
||||
var target = CreateTargetWithSource(
|
||||
data,
|
||||
|
||||
Reference in New Issue
Block a user