diff --git a/src/CommunityToolkit.Maui.Core/Primitives/Defaults/MultiValidationBehaviorDefaults.cs b/src/CommunityToolkit.Maui.Core/Primitives/Defaults/MultiValidationBehaviorDefaults.cs new file mode 100644 index 0000000000..d00c67d116 --- /dev/null +++ b/src/CommunityToolkit.Maui.Core/Primitives/Defaults/MultiValidationBehaviorDefaults.cs @@ -0,0 +1,7 @@ +namespace CommunityToolkit.Maui.Core; + +static class MultiValidationBehaviorDefaults +{ + public static List? Errors { get; } = null; + public static List? Error { get; } = null; +} \ No newline at end of file diff --git a/src/CommunityToolkit.Maui.Core/Primitives/Defaults/NumericValidationBehaviorDefaults.cs b/src/CommunityToolkit.Maui.Core/Primitives/Defaults/NumericValidationBehaviorDefaults.cs new file mode 100644 index 0000000000..7ff98502f8 --- /dev/null +++ b/src/CommunityToolkit.Maui.Core/Primitives/Defaults/NumericValidationBehaviorDefaults.cs @@ -0,0 +1,9 @@ +namespace CommunityToolkit.Maui.Core; + +static class NumericValidationBehaviorDefaults +{ + public const double MinimumValue = double.NegativeInfinity; + public const double MaximumValue = double.PositiveInfinity; + public const int MinimumDecimalPlaces = 0; + public const int MaximumDecimalPlaces = int.MaxValue; +} \ No newline at end of file diff --git a/src/CommunityToolkit.Maui.Core/Primitives/Defaults/RequiredStringValidationBehaviorDefaults.cs b/src/CommunityToolkit.Maui.Core/Primitives/Defaults/RequiredStringValidationBehaviorDefaults.cs new file mode 100644 index 0000000000..3e6267dd16 --- /dev/null +++ b/src/CommunityToolkit.Maui.Core/Primitives/Defaults/RequiredStringValidationBehaviorDefaults.cs @@ -0,0 +1,7 @@ +namespace CommunityToolkit.Maui.Core; + +static class RequiredStringValidationBehaviorDefaults +{ + public const string? RequiredString = null; + public const bool ExactMatch = true; +} \ No newline at end of file diff --git a/src/CommunityToolkit.Maui.Core/Primitives/Defaults/UriValidationBehaviorDefaults.cs b/src/CommunityToolkit.Maui.Core/Primitives/Defaults/UriValidationBehaviorDefaults.cs new file mode 100644 index 0000000000..2508ad3877 --- /dev/null +++ b/src/CommunityToolkit.Maui.Core/Primitives/Defaults/UriValidationBehaviorDefaults.cs @@ -0,0 +1,6 @@ +namespace CommunityToolkit.Maui.Core; + +static class UriValidationBehaviorDefaults +{ + public static UriKind UriKind { get; } = UriKind.RelativeOrAbsolute; +} \ No newline at end of file diff --git a/src/CommunityToolkit.Maui.UnitTests/Behaviors/CharactersValidationBehaviorTests.cs b/src/CommunityToolkit.Maui.UnitTests/Behaviors/CharactersValidationBehaviorTests.cs index 2381f67561..45283695e4 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Behaviors/CharactersValidationBehaviorTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Behaviors/CharactersValidationBehaviorTests.cs @@ -1,4 +1,5 @@ using CommunityToolkit.Maui.Behaviors; +using CommunityToolkit.Maui.Core; using Nito.AsyncEx; using Xunit; @@ -125,4 +126,14 @@ public void EnsureObjectDisposedExceptionThrownWhenDisposedBehaviorAttachedToVis }); }); } + + [Fact] + public void VerifyDefaults() + { + var charactersValidationBehavior = new CharactersValidationBehavior(); + + Assert.Equal(CharactersValidationBehaviorDefaults.CharacterType, charactersValidationBehavior.CharacterType); + Assert.Equal(CharactersValidationBehaviorDefaults.MaximumCharacterTypeCount, charactersValidationBehavior.MaximumCharacterTypeCount); + Assert.Equal(CharactersValidationBehaviorDefaults.MinimumCharacterTypeCount, charactersValidationBehavior.MinimumCharacterTypeCount); + } } \ No newline at end of file diff --git a/src/CommunityToolkit.Maui.UnitTests/Behaviors/MultiValidationBehaviorTests.cs b/src/CommunityToolkit.Maui.UnitTests/Behaviors/MultiValidationBehaviorTests.cs index f35088e4b7..973ac580ce 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Behaviors/MultiValidationBehaviorTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Behaviors/MultiValidationBehaviorTests.cs @@ -1,4 +1,5 @@ using CommunityToolkit.Maui.Behaviors; +using CommunityToolkit.Maui.Core; using Xunit; namespace CommunityToolkit.Maui.UnitTests.Behaviors; @@ -119,4 +120,15 @@ public async Task ForceValidateCancellationTokenCanceled() // Assert await Assert.ThrowsAsync(async () => await multiBehavior.ForceValidate(cts.Token)); } + + [Fact] + public void VerifyDefaults() + { + // Arrange + var multiValidationBehavior = new MultiValidationBehavior(); + + // Act // Assert + Assert.Equal(MultiValidationBehaviorDefaults.Errors, multiValidationBehavior.Errors); + Assert.Equal(MultiValidationBehaviorDefaults.Error, MultiValidationBehavior.GetError(multiValidationBehavior)); + } } \ No newline at end of file diff --git a/src/CommunityToolkit.Maui.UnitTests/Behaviors/NumericValidationBehaviorTests.cs b/src/CommunityToolkit.Maui.UnitTests/Behaviors/NumericValidationBehaviorTests.cs index 9f3ea88883..2bbfb20424 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Behaviors/NumericValidationBehaviorTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Behaviors/NumericValidationBehaviorTests.cs @@ -1,5 +1,6 @@ using System.Globalization; using CommunityToolkit.Maui.Behaviors; +using CommunityToolkit.Maui.Core; using FluentAssertions; using Xunit; @@ -163,4 +164,17 @@ await Assert.ThrowsAsync(async () => await behavior.ForceValidate(cts.Token); }); } + + [Fact] + public void VerifyDefaults() + { + // Arrange + var numericValidationBehavior = new NumericValidationBehavior(); + + // Act Assert + Assert.Equal(NumericValidationBehaviorDefaults.MaximumDecimalPlaces, numericValidationBehavior.MaximumDecimalPlaces); + Assert.Equal(NumericValidationBehaviorDefaults.MaximumValue, numericValidationBehavior.MaximumValue); + Assert.Equal(NumericValidationBehaviorDefaults.MinimumDecimalPlaces, numericValidationBehavior.MinimumDecimalPlaces); + Assert.Equal(NumericValidationBehaviorDefaults.MinimumValue, numericValidationBehavior.MinimumValue); + } } \ No newline at end of file diff --git a/src/CommunityToolkit.Maui.UnitTests/Behaviors/RequiredStringValidationBehaviorTests.cs b/src/CommunityToolkit.Maui.UnitTests/Behaviors/RequiredStringValidationBehaviorTests.cs index 382bbc6ddb..31341c3434 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Behaviors/RequiredStringValidationBehaviorTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Behaviors/RequiredStringValidationBehaviorTests.cs @@ -1,5 +1,6 @@ using System.Globalization; using CommunityToolkit.Maui.Behaviors; +using CommunityToolkit.Maui.Core; using Xunit; namespace CommunityToolkit.Maui.UnitTests.Behaviors; @@ -157,4 +158,15 @@ public void IsValidFalseWhenEnterDifferentText_Test() // Assert Assert.False(confirmPasswordBehavior.IsValid); } + + [Fact] + public void VerifyDefaults() + { + // Arrange + var requiredStringValidationBehavior = new RequiredStringValidationBehavior(); + + // Act Assert + Assert.Equal(RequiredStringValidationBehaviorDefaults.ExactMatch, requiredStringValidationBehavior.ExactMatch); + Assert.Equal(RequiredStringValidationBehaviorDefaults.RequiredString, requiredStringValidationBehavior.RequiredString); + } } \ No newline at end of file diff --git a/src/CommunityToolkit.Maui.UnitTests/Behaviors/TextValidationBehaviorTests.cs b/src/CommunityToolkit.Maui.UnitTests/Behaviors/TextValidationBehaviorTests.cs index 4b8020514f..e70078232f 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Behaviors/TextValidationBehaviorTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Behaviors/TextValidationBehaviorTests.cs @@ -84,4 +84,18 @@ await Assert.ThrowsAsync(async () => await behavior.ForceValidate(cts.Token); }); } + + [Fact] + public void VerifyDefaults() + { + // Arrange + var textValidationBehavior = new TextValidationBehavior(); + + // Act Assert + Assert.Equal(TextValidationBehaviorDefaults.DecorationFlags, textValidationBehavior.DecorationFlags); + Assert.Equal(TextValidationBehaviorDefaults.MaximumLength, textValidationBehavior.MaximumLength); + Assert.Equal(TextValidationBehaviorDefaults.MinimumLength, textValidationBehavior.MinimumLength); + Assert.Equal(TextValidationBehaviorDefaults.RegexOptions, textValidationBehavior.RegexOptions); + Assert.Equal(TextValidationBehaviorDefaults.RegexPattern, textValidationBehavior.RegexPattern); + } } \ No newline at end of file diff --git a/src/CommunityToolkit.Maui.UnitTests/Behaviors/UriValidationBehaviorTests.cs b/src/CommunityToolkit.Maui.UnitTests/Behaviors/UriValidationBehaviorTests.cs index 3cc432155b..25c33fb071 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Behaviors/UriValidationBehaviorTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Behaviors/UriValidationBehaviorTests.cs @@ -1,4 +1,5 @@ using CommunityToolkit.Maui.Behaviors; +using CommunityToolkit.Maui.Core; using Xunit; namespace CommunityToolkit.Maui.UnitTests.Behaviors; @@ -75,4 +76,14 @@ await Assert.ThrowsAsync(async () => await behavior.ForceValidate(cts.Token); }); } + + [Fact] + public void VerifyDefaults() + { + // Arrange + var behavior = new UriValidationBehavior(); + + // Act Assert + Assert.Equal(UriValidationBehaviorDefaults.UriKind, behavior.UriKind); + } } \ No newline at end of file diff --git a/src/CommunityToolkit.Maui.UnitTests/Behaviors/ValidationBehaviorTests.cs b/src/CommunityToolkit.Maui.UnitTests/Behaviors/ValidationBehaviorTests.cs index 834e3dbb1a..42ee4f26e4 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Behaviors/ValidationBehaviorTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Behaviors/ValidationBehaviorTests.cs @@ -245,6 +245,24 @@ public void TestRemoveValidationBindingWithoutBindingContext() Assert.Empty(view.Behaviors); } + + [Fact] + public void VerifyDefaults() + { + // Arrange + var behavior = new MockValidationBehavior(); + + // Act Assert + Assert.Equal(ValidationBehaviorDefaults.IsNotValid, behavior.IsNotValid); + Assert.Equal(ValidationBehaviorDefaults.IsValid, behavior.IsValid); + Assert.Equal(ValidationBehaviorDefaults.IsRunning, behavior.IsRunning); + Assert.Equal(ValidationBehaviorDefaults.ValidStyle, behavior.ValidStyle); + Assert.Equal(ValidationBehaviorDefaults.InvalidStyle, behavior.InvalidStyle); + Assert.Equal(ValidationBehaviorDefaults.Value, behavior.Value); + Assert.Equal(ValidationBehaviorDefaults.ValuePropertyName, behavior.ValuePropertyName); + Assert.Equal(ValidationBehaviorDefaults.Flags, behavior.Flags); + + } } public class StyleSetterComparer(ITestOutputHelper testOutputHelper) : IEqualityComparer diff --git a/src/CommunityToolkit.Maui/Behaviors/Validators/CharactersValidationBehavior.shared.cs b/src/CommunityToolkit.Maui/Behaviors/Validators/CharactersValidationBehavior.shared.cs index 0ffdafc7e0..742c32c770 100644 --- a/src/CommunityToolkit.Maui/Behaviors/Validators/CharactersValidationBehavior.shared.cs +++ b/src/CommunityToolkit.Maui/Behaviors/Validators/CharactersValidationBehavior.shared.cs @@ -1,4 +1,5 @@ -using System.Diagnostics.CodeAnalysis; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; namespace CommunityToolkit.Maui.Behaviors; /// The allowed character types used to determine if a value is valid in the . Since this is a flag, multiple flags cane be combined. @@ -47,25 +48,7 @@ public enum CharacterType [RequiresUnreferencedCode($"{nameof(CharactersValidationBehavior)} is not trim safe because it uses bindings with string paths.")] public partial class CharactersValidationBehavior : TextValidationBehavior { - List> characterPredicates = Enumerable.Empty>().ToList(); - - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty CharacterTypeProperty = - BindableProperty.Create(nameof(CharacterType), typeof(CharacterType), typeof(CharactersValidationBehavior), CharacterType.Any, propertyChanged: OnCharacterTypePropertyChanged); - - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty MinimumCharacterTypeCountProperty = - BindableProperty.Create(nameof(MinimumCharacterTypeCount), typeof(int), typeof(CharactersValidationBehavior), 0, propertyChanged: OnValidationPropertyChanged); - - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty MaximumCharacterTypeCountProperty = - BindableProperty.Create(nameof(MaximumCharacterTypeCount), typeof(int), typeof(CharactersValidationBehavior), int.MaxValue, propertyChanged: OnValidationPropertyChanged); + List> characterPredicates = []; /// /// Constructor for this behavior @@ -75,29 +58,20 @@ public partial class CharactersValidationBehavior : TextValidationBehavior /// /// Provides an enumerated value to use to set how to handle comparisons. This is a bindable property. /// - public CharacterType CharacterType - { - get => (CharacterType)GetValue(CharacterTypeProperty); - set => SetValue(CharacterTypeProperty, value); - } + [BindableProperty(PropertyChangedMethodName = nameof(OnCharacterTypePropertyChanged))] + public partial CharacterType CharacterType { get; set; } = CharactersValidationBehaviorDefaults.CharacterType; /// /// The minimum number of required. This is a bindable property. /// - public int MinimumCharacterTypeCount - { - get => (int)GetValue(MinimumCharacterTypeCountProperty); - set => SetValue(MinimumCharacterTypeCountProperty, value); - } + [BindableProperty(PropertyChangedMethodName = nameof(OnValidationPropertyChanged))] + public partial int MinimumCharacterTypeCount { get; set; } = CharactersValidationBehaviorDefaults.MinimumCharacterTypeCount; /// /// The maximum number of allowed. This is a bindable property. /// - public int MaximumCharacterTypeCount - { - get => (int)GetValue(MaximumCharacterTypeCountProperty); - set => SetValue(MaximumCharacterTypeCountProperty, value); - } + [BindableProperty(PropertyChangedMethodName = nameof(OnValidationPropertyChanged))] + public partial int MaximumCharacterTypeCount { get; set; } = CharactersValidationBehaviorDefaults.MaximumCharacterTypeCount; /// protected override async ValueTask ValidateAsync(string? value, CancellationToken token) diff --git a/src/CommunityToolkit.Maui/Behaviors/Validators/MultiValidationBehavior.shared.cs b/src/CommunityToolkit.Maui/Behaviors/Validators/MultiValidationBehavior.shared.cs index a39e681bc8..b34df542f1 100644 --- a/src/CommunityToolkit.Maui/Behaviors/Validators/MultiValidationBehavior.shared.cs +++ b/src/CommunityToolkit.Maui/Behaviors/Validators/MultiValidationBehavior.shared.cs @@ -1,5 +1,6 @@ using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; +using CommunityToolkit.Maui.Core; namespace CommunityToolkit.Maui.Behaviors; @@ -11,12 +12,6 @@ namespace CommunityToolkit.Maui.Behaviors; [ContentProperty(nameof(Children))] public partial class MultiValidationBehavior : ValidationBehavior { - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty ErrorsProperty = - BindableProperty.Create(nameof(Errors), typeof(List), typeof(MultiValidationBehavior), null, BindingMode.OneWayToSource); - /// /// BindableProperty for getting the error. /// @@ -33,11 +28,8 @@ public partial class MultiValidationBehavior : ValidationBehavior /// /// Holds the errors from all the nested invalid validators in . This is a bindable property. /// - public List? Errors - { - get => (List?)GetValue(ErrorsProperty); - set => SetValue(ErrorsProperty, value); - } + [BindableProperty(DefaultBindingMode = BindingMode.OneWayToSource)] + public partial List? Errors { get; set; } = MultiValidationBehaviorDefaults.Errors; /// /// Method to extract the error from the attached property for a child behavior in . diff --git a/src/CommunityToolkit.Maui/Behaviors/Validators/NumericValidationBehavior.shared.cs b/src/CommunityToolkit.Maui/Behaviors/Validators/NumericValidationBehavior.shared.cs index ad12c4f1ae..c4f509e723 100644 --- a/src/CommunityToolkit.Maui/Behaviors/Validators/NumericValidationBehavior.shared.cs +++ b/src/CommunityToolkit.Maui/Behaviors/Validators/NumericValidationBehavior.shared.cs @@ -1,5 +1,7 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; +using CommunityToolkit.Maui.Core; + namespace CommunityToolkit.Maui.Behaviors; /// @@ -9,65 +11,29 @@ namespace CommunityToolkit.Maui.Behaviors; [RequiresUnreferencedCode($"{nameof(NumericValidationBehavior)} is not trim safe because it uses bindings with string paths.")] public partial class NumericValidationBehavior : ValidationBehavior { - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty MinimumValueProperty = - BindableProperty.Create(nameof(MinimumValue), typeof(double), typeof(NumericValidationBehavior), double.NegativeInfinity, propertyChanged: OnValidationPropertyChanged); - - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty MaximumValueProperty = - BindableProperty.Create(nameof(MaximumValue), typeof(double), typeof(NumericValidationBehavior), double.PositiveInfinity, propertyChanged: OnValidationPropertyChanged); - - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty MinimumDecimalPlacesProperty = - BindableProperty.Create(nameof(MinimumDecimalPlaces), typeof(int), typeof(NumericValidationBehavior), 0, propertyChanged: OnValidationPropertyChanged); - - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty MaximumDecimalPlacesProperty = - BindableProperty.Create(nameof(MaximumDecimalPlaces), typeof(int), typeof(NumericValidationBehavior), int.MaxValue, propertyChanged: OnValidationPropertyChanged); - /// /// The minimum numeric value that will be allowed. This is a bindable property. /// - public double MinimumValue - { - get => (double)GetValue(MinimumValueProperty); - set => SetValue(MinimumValueProperty, value); - } + [BindableProperty(PropertyChangedMethodName = nameof(OnValidationPropertyChanged))] + public partial double MinimumValue { get; set; } = NumericValidationBehaviorDefaults.MinimumValue; /// /// The maximum numeric value that will be allowed. This is a bindable property. /// - public double MaximumValue - { - get => (double)GetValue(MaximumValueProperty); - set => SetValue(MaximumValueProperty, value); - } + [BindableProperty(PropertyChangedMethodName = nameof(OnValidationPropertyChanged))] + public partial double MaximumValue { get; set; } = NumericValidationBehaviorDefaults.MaximumValue; /// /// The minimum number of decimal places that will be allowed. This is a bindable property. /// - public int MinimumDecimalPlaces - { - get => (int)GetValue(MinimumDecimalPlacesProperty); - set => SetValue(MinimumDecimalPlacesProperty, value); - } + [BindableProperty(PropertyChangedMethodName = nameof(OnValidationPropertyChanged))] + public partial int MinimumDecimalPlaces { get; set; } = NumericValidationBehaviorDefaults.MinimumDecimalPlaces; /// /// The maximum number of decimal places that will be allowed. This is a bindable property. /// - public int MaximumDecimalPlaces - { - get => (int)GetValue(MaximumDecimalPlacesProperty); - set => SetValue(MaximumDecimalPlacesProperty, value); - } + [BindableProperty(PropertyChangedMethodName = nameof(OnValidationPropertyChanged))] + public partial int MaximumDecimalPlaces { get; set; } = NumericValidationBehaviorDefaults.MaximumDecimalPlaces; /// protected override string? Decorate(string? value) diff --git a/src/CommunityToolkit.Maui/Behaviors/Validators/RequiredStringValidationBehavior.shared.cs b/src/CommunityToolkit.Maui/Behaviors/Validators/RequiredStringValidationBehavior.shared.cs index 70d8f6bb0d..aa23ad055f 100644 --- a/src/CommunityToolkit.Maui/Behaviors/Validators/RequiredStringValidationBehavior.shared.cs +++ b/src/CommunityToolkit.Maui/Behaviors/Validators/RequiredStringValidationBehavior.shared.cs @@ -1,4 +1,6 @@ using System.Diagnostics.CodeAnalysis; +using CommunityToolkit.Maui.Core; + namespace CommunityToolkit.Maui.Behaviors; /// @@ -8,26 +10,11 @@ namespace CommunityToolkit.Maui.Behaviors; [RequiresUnreferencedCode($"{nameof(RequiredStringValidationBehavior)} is not trim safe because it uses bindings with string paths.")] public partial class RequiredStringValidationBehavior : ValidationBehavior { - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty RequiredStringProperty - = BindableProperty.Create(nameof(RequiredString), typeof(string), typeof(RequiredStringValidationBehavior)); - - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty ExactMatchProperty - = BindableProperty.Create(nameof(ExactMatch), typeof(bool), typeof(RequiredStringValidationBehavior), true); - /// /// The string that will be compared to the value provided by the user. This is a bindable property. /// - public string? RequiredString - { - get => (string?)GetValue(RequiredStringProperty); - set => SetValue(RequiredStringProperty, value); - } + [BindableProperty] + public partial string? RequiredString { get; set; } = RequiredStringValidationBehaviorDefaults.RequiredString; /// /// Get or sets whether the entered text must match the whole contents of the property @@ -35,11 +22,8 @@ public string? RequiredString ///
/// true by default. This is a bindable property. ///
- public bool ExactMatch - { - get => (bool)GetValue(ExactMatchProperty); - set => SetValue(ExactMatchProperty, value); - } + [BindableProperty] + public partial bool ExactMatch { get; set; } = RequiredStringValidationBehaviorDefaults.ExactMatch; /// protected override ValueTask ValidateAsync(string? value, CancellationToken token) diff --git a/src/CommunityToolkit.Maui/Behaviors/Validators/TextValidationBehavior.shared.cs b/src/CommunityToolkit.Maui/Behaviors/Validators/TextValidationBehavior.shared.cs index d44f7908b5..2ddddf05a3 100644 --- a/src/CommunityToolkit.Maui/Behaviors/Validators/TextValidationBehavior.shared.cs +++ b/src/CommunityToolkit.Maui/Behaviors/Validators/TextValidationBehavior.shared.cs @@ -10,14 +10,19 @@ public enum TextDecorationFlags { /// No text decoration will be applied. None = 0, + /// is applied on the value prior to validation. TrimStart = 1, + /// is applied on the value prior to validation. TrimEnd = 2, + /// is applied on the value prior to validation. Trim = TrimStart | TrimEnd, + /// If is null, replace the value with NullToEmpty = 4, + /// Excessive white space is removed from prior to validation. I.e. I.e. "Hello World" will become "Hello World". This applies to whitespace found anywhere. NormalizeWhiteSpace = 8 } @@ -29,36 +34,6 @@ public enum TextDecorationFlags [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] public partial class TextValidationBehavior : ValidationBehavior { - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty MinimumLengthProperty = - BindableProperty.Create(nameof(MinimumLength), typeof(int), typeof(TextValidationBehavior), 0, propertyChanged: OnValidationPropertyChanged); - - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty MaximumLengthProperty = - BindableProperty.Create(nameof(MaximumLength), typeof(int), typeof(TextValidationBehavior), int.MaxValue, propertyChanged: OnValidationPropertyChanged); - - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty DecorationFlagsProperty = - BindableProperty.Create(nameof(DecorationFlags), typeof(TextDecorationFlags), typeof(TextValidationBehavior), TextDecorationFlags.None, propertyChanged: OnValidationPropertyChanged); - - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty RegexPatternProperty = - BindableProperty.Create(nameof(RegexPattern), typeof(string), typeof(TextValidationBehavior), defaultValueCreator: GetDefaultRegexPattern, propertyChanged: OnRegexPropertyChanged); - - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty RegexOptionsProperty = - BindableProperty.Create(nameof(RegexOptions), typeof(RegexOptions), typeof(TextValidationBehavior), defaultValueCreator: GetDefaultRegexOptions, propertyChanged: OnRegexPropertyChanged); - Regex? regex; /// @@ -67,59 +42,44 @@ public partial class TextValidationBehavior : ValidationBehavior public TextValidationBehavior() => OnRegexPropertyChanged(RegexPattern, RegexOptions); /// - /// Default regex pattern + /// The minimum length of the value that will be allowed. This is a bindable property. /// - protected virtual string DefaultRegexPattern { get; } = string.Empty; + [BindableProperty(PropertyChangedMethodName = nameof(OnValidationPropertyChanged))] + public partial int MinimumLength { get; set; } = TextValidationBehaviorDefaults.MinimumLength; /// - /// Default regex options + /// The maximum length of the value that will be allowed. This is a bindable property. /// - protected virtual RegexOptions DefaultRegexOptions { get; } = RegexOptions.None; + [BindableProperty(PropertyChangedMethodName = nameof(OnValidationPropertyChanged))] + public partial int MaximumLength { get; set; } = TextValidationBehaviorDefaults.MaximumLength; /// - /// The minimum length of the value that will be allowed. This is a bindable property. + /// Provides enumerated value to use to set how to handle white spaces. This is a bindable property. /// - public int MinimumLength - { - get => (int)GetValue(MinimumLengthProperty); - set => SetValue(MinimumLengthProperty, value); - } + [BindableProperty(PropertyChangedMethodName = nameof(OnValidationPropertyChanged))] + public partial TextDecorationFlags DecorationFlags { get; set; } = TextValidationBehaviorDefaults.DecorationFlags; /// - /// The maximum length of the value that will be allowed. This is a bindable property. + /// The regular expression pattern which the value will have to match before it will be allowed. This is a bindable property. /// - public int MaximumLength - { - get => (int)GetValue(MaximumLengthProperty); - set => SetValue(MaximumLengthProperty, value); - } + [BindableProperty(DefaultValueCreatorMethodName = nameof(GetDefaultRegexPattern), PropertyChangedMethodName = nameof(OnRegexPropertyChanged))] + public partial string? RegexPattern { get; set; } /// - /// Provides enumerated value to use to set how to handle white spaces. This is a bindable property. + /// Provides enumerated values to use to set regular expression options. This is a bindable property. /// - public TextDecorationFlags DecorationFlags - { - get => (TextDecorationFlags)GetValue(DecorationFlagsProperty); - set => SetValue(DecorationFlagsProperty, value); - } + [BindableProperty(DefaultValueCreatorMethodName = nameof(GetDefaultRegexOptions), PropertyChangedMethodName = nameof(OnRegexPropertyChanged))] + public partial RegexOptions RegexOptions { get; set; } /// - /// The regular expression pattern which the value will have to match before it will be allowed. This is a bindable property. + /// Default regex pattern /// - public string? RegexPattern - { - get => (string?)GetValue(RegexPatternProperty); - set => SetValue(RegexPatternProperty, value); - } + protected virtual string DefaultRegexPattern { get; } = TextValidationBehaviorDefaults.RegexPattern; /// - /// Provides enumerated values to use to set regular expression options. This is a bindable property. + /// Default regex options /// - public RegexOptions RegexOptions - { - get => (RegexOptions)GetValue(RegexOptionsProperty); - set => SetValue(RegexOptionsProperty, value); - } + protected virtual RegexOptions DefaultRegexOptions { get; } = TextValidationBehaviorDefaults.RegexOptions; /// protected override string? Decorate(string? value) diff --git a/src/CommunityToolkit.Maui/Behaviors/Validators/UriValidationBehavior.shared.cs b/src/CommunityToolkit.Maui/Behaviors/Validators/UriValidationBehavior.shared.cs index 0a36b70217..e728236776 100644 --- a/src/CommunityToolkit.Maui/Behaviors/Validators/UriValidationBehavior.shared.cs +++ b/src/CommunityToolkit.Maui/Behaviors/Validators/UriValidationBehavior.shared.cs @@ -1,4 +1,6 @@ using System.Diagnostics.CodeAnalysis; +using CommunityToolkit.Maui.Core; + namespace CommunityToolkit.Maui.Behaviors; /// @@ -8,20 +10,11 @@ namespace CommunityToolkit.Maui.Behaviors; [RequiresUnreferencedCode($"{nameof(UriValidationBehavior)} is not trim safe because it uses bindings with string paths.")] public partial class UriValidationBehavior : TextValidationBehavior { - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty UriKindProperty = - BindableProperty.Create(nameof(UriKind), typeof(UriKind), typeof(UriValidationBehavior), UriKind.RelativeOrAbsolute, propertyChanged: OnValidationPropertyChanged); - /// /// Provides an enumerated value that specifies how to handle different URI types. This is a bindable property. /// - public UriKind UriKind - { - get => (UriKind)GetValue(UriKindProperty); - set => SetValue(UriKindProperty, value); - } + [BindableProperty(PropertyChangedMethodName = nameof(OnValidationPropertyChanged))] + public partial UriKind UriKind { get; set; } = UriValidationBehaviorDefaults.UriKind; /// protected override async ValueTask ValidateAsync(string? value, CancellationToken token) diff --git a/src/CommunityToolkit.Maui/Behaviors/Validators/ValidationBehavior.shared.cs b/src/CommunityToolkit.Maui/Behaviors/Validators/ValidationBehavior.shared.cs index 797ccdd884..069c1775d1 100644 --- a/src/CommunityToolkit.Maui/Behaviors/Validators/ValidationBehavior.shared.cs +++ b/src/CommunityToolkit.Maui/Behaviors/Validators/ValidationBehavior.shared.cs @@ -11,14 +11,19 @@ public enum ValidationFlags { /// No validation None = 0, + /// Validate on attaching ValidateOnAttaching = 1, + /// Validate on focusing ValidateOnFocused = 2, + /// Validate on unfocus ValidateOnUnfocused = 4, + /// Validate upon value changed ValidateOnValueChanged = 8, + /// Force make valid when focused ForceMakeValidWhenFocused = 16 } @@ -28,7 +33,7 @@ public enum ValidationFlags /// [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] [RequiresUnreferencedCode($"{nameof(ValidationBehavior)} is not trim safe because it uses bindings with string paths.")] -public abstract class ValidationBehavior : BaseBehavior, IDisposable +public abstract partial class ValidationBehavior : BaseBehavior, IDisposable { /// /// Valid visual state @@ -40,60 +45,6 @@ public abstract class ValidationBehavior : BaseBehavior, IDisposa /// public const string InvalidVisualState = "Invalid"; - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty IsNotValidProperty = - BindableProperty.Create(nameof(IsNotValid), typeof(bool), typeof(ValidationBehavior), false, BindingMode.OneWayToSource); - - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty IsValidProperty = - BindableProperty.Create(nameof(IsValid), typeof(bool), typeof(ValidationBehavior), true, BindingMode.OneWayToSource, propertyChanged: OnIsValidPropertyChanged); - - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty IsRunningProperty = - BindableProperty.Create(nameof(IsRunning), typeof(bool), typeof(ValidationBehavior), false, BindingMode.OneWayToSource); - - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty ValidStyleProperty = - BindableProperty.Create(nameof(ValidStyle), typeof(Style), typeof(ValidationBehavior), propertyChanged: OnValidationPropertyChanged); - - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty InvalidStyleProperty = - BindableProperty.Create(nameof(InvalidStyle), typeof(Style), typeof(ValidationBehavior), propertyChanged: OnValidationPropertyChanged); - - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty FlagsProperty = - BindableProperty.Create(nameof(Flags), typeof(ValidationFlags), typeof(ValidationBehavior), ValidationFlags.ValidateOnUnfocused | ValidationFlags.ForceMakeValidWhenFocused, propertyChanged: OnValidationPropertyChanged); - - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty ValueProperty = - BindableProperty.Create(nameof(Value), typeof(object), typeof(ValidationBehavior), propertyChanged: OnValuePropertyChanged); - - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty ValuePropertyNameProperty = - BindableProperty.Create(nameof(ValuePropertyName), typeof(string), typeof(ValidationBehavior), defaultValueCreator: GetDefaultValuePropertyName, propertyChanged: OnValuePropertyNamePropertyChanged); - - /// - /// Backing BindableProperty for the property. - /// - public static readonly BindableProperty ForceValidateCommandProperty = - BindableProperty.Create(nameof(ForceValidateCommand), typeof(ICommand), typeof(ValidationBehavior), defaultValueCreator: GetDefaultForceValidateCommand, defaultBindingMode: BindingMode.OneWayToSource); - readonly SemaphoreSlim isAttachingSemaphoreSlim = new(1, 1); ValidationFlags currentStatus; @@ -121,74 +72,50 @@ protected ValidationBehavior() /// /// Indicates whether the current value is considered valid. This is a bindable property. /// - public bool IsValid - { - get => (bool)GetValue(IsValidProperty); - set => SetValue(IsValidProperty, value); - } + [BindableProperty(DefaultBindingMode = BindingMode.OneWayToSource, PropertyChangedMethodName = nameof(OnIsValidPropertyChanged))] + public partial bool IsValid { get; set; } = ValidationBehaviorDefaults.IsValid; /// /// Indicates whether the validation is in progress now (waiting for an asynchronous call is finished). /// - public bool IsRunning - { - get => (bool)GetValue(IsRunningProperty); - set => SetValue(IsRunningProperty, value); - } + [BindableProperty(DefaultBindingMode = BindingMode.OneWayToSource)] + public partial bool IsRunning { get; set; } = ValidationBehaviorDefaults.IsRunning; /// /// Indicates whether the current value is considered not valid. This is a bindable property. /// - public bool IsNotValid - { - get => (bool)GetValue(IsNotValidProperty); - set => SetValue(IsNotValidProperty, value); - } + [BindableProperty(DefaultBindingMode = BindingMode.OneWayToSource)] + public partial bool IsNotValid { get; set; } = ValidationBehaviorDefaults.IsNotValid; /// /// The to apply to the element when validation is successful. This is a bindable property. /// - public Style? ValidStyle - { - get => (Style?)GetValue(ValidStyleProperty); - set => SetValue(ValidStyleProperty, value); - } + [BindableProperty(PropertyChangedMethodName = nameof(OnValidationPropertyChanged))] + public partial Style? ValidStyle { get; set; } = ValidationBehaviorDefaults.ValidStyle; /// /// The to apply to the element when validation fails. This is a bindable property. /// - public Style? InvalidStyle - { - get => (Style?)GetValue(InvalidStyleProperty); - set => SetValue(InvalidStyleProperty, value); - } + [BindableProperty(PropertyChangedMethodName = nameof(OnValidationPropertyChanged))] + public partial Style? InvalidStyle { get; set; } = ValidationBehaviorDefaults.InvalidStyle; /// /// Provides an enumerated value that specifies how to handle validation. This is a bindable property. /// - public ValidationFlags Flags - { - get => (ValidationFlags)GetValue(FlagsProperty); - set => SetValue(FlagsProperty, value); - } + [BindableProperty(PropertyChangedMethodName = nameof(OnValidationPropertyChanged))] + public partial ValidationFlags Flags { get; set; } = ValidationBehaviorDefaults.Flags; /// /// The value to validate. This is a bindable property. /// - public object? Value - { - get => (object?)GetValue(ValueProperty); - set => SetValue(ValueProperty, value); - } + [BindableProperty(PropertyChangedMethodName = nameof(OnValuePropertyChanged))] + public partial object? Value { get; set; } = ValidationBehaviorDefaults.Value; /// /// Allows the user to override the property that will be used as the value to validate. This is a bindable property. /// - public string? ValuePropertyName - { - get => (string?)GetValue(ValuePropertyNameProperty); - set => SetValue(ValuePropertyNameProperty, value); - } + [BindableProperty(DefaultValueCreatorMethodName = nameof(GetDefaultValuePropertyName), PropertyChangedMethodName = nameof(OnValuePropertyNamePropertyChanged))] + public partial string? ValuePropertyName { get; set; } /// /// Allows the user to provide a custom that handles forcing validation. This is a bindable property. @@ -196,16 +123,13 @@ public string? ValuePropertyName /// /// The Default Value for has a of Command<CancellationToken> which requires a as a CommandParameter. See and for more information on passing a into as a CommandParameter" /// - public ICommand ForceValidateCommand - { - get => (ICommand)GetValue(ForceValidateCommandProperty); - set => SetValue(ForceValidateCommandProperty, value); - } + [BindableProperty(DefaultBindingMode = BindingMode.OneWayToSource, DefaultValueCreatorMethodName = nameof(GetDefaultForceValidateCommand))] + public partial ICommand ForceValidateCommand { get; set; } /// /// Default value property name /// - protected virtual string DefaultValuePropertyName { get; } = Entry.TextProperty.PropertyName; + protected virtual string DefaultValuePropertyName { get; } = ValidationBehaviorDefaults.ValuePropertyName; /// /// Default force validate command @@ -424,7 +348,9 @@ void ResetValidationTokenSource(CancellationTokenSource? newTokenSource) validationTokenSource?.Cancel(); validationTokenSource?.Dispose(); } - catch (ObjectDisposedException) { } + catch (ObjectDisposedException) + { + } finally { validationTokenSource = newTokenSource; diff --git a/src/CommunityToolkit.Maui/Primitives/Defaults/CharactersValidationBehaviorDefaults.cs b/src/CommunityToolkit.Maui/Primitives/Defaults/CharactersValidationBehaviorDefaults.cs new file mode 100644 index 0000000000..b96420d141 --- /dev/null +++ b/src/CommunityToolkit.Maui/Primitives/Defaults/CharactersValidationBehaviorDefaults.cs @@ -0,0 +1,11 @@ +using CommunityToolkit.Maui.Behaviors; + +namespace CommunityToolkit.Maui; + +static class CharactersValidationBehaviorDefaults +{ + public const int MaximumCharacterTypeCount = int.MaxValue; + public const int MinimumCharacterTypeCount = 0; + + public static CharacterType CharacterType { get; } = CharacterType.Any; +} \ No newline at end of file diff --git a/src/CommunityToolkit.Maui/Primitives/DefaultPopupOptionsSettings.shared.cs b/src/CommunityToolkit.Maui/Primitives/Defaults/DefaultPopupOptionsSettings.cs similarity index 100% rename from src/CommunityToolkit.Maui/Primitives/DefaultPopupOptionsSettings.shared.cs rename to src/CommunityToolkit.Maui/Primitives/Defaults/DefaultPopupOptionsSettings.cs diff --git a/src/CommunityToolkit.Maui/Primitives/DefaultPopupSettings.shared.cs b/src/CommunityToolkit.Maui/Primitives/Defaults/DefaultPopupSettings.cs similarity index 100% rename from src/CommunityToolkit.Maui/Primitives/DefaultPopupSettings.shared.cs rename to src/CommunityToolkit.Maui/Primitives/Defaults/DefaultPopupSettings.cs diff --git a/src/CommunityToolkit.Maui/Primitives/GravatarImageSourceDefaults.shared.cs b/src/CommunityToolkit.Maui/Primitives/Defaults/GravatarImageSourceDefaults.shared.cs similarity index 100% rename from src/CommunityToolkit.Maui/Primitives/GravatarImageSourceDefaults.shared.cs rename to src/CommunityToolkit.Maui/Primitives/Defaults/GravatarImageSourceDefaults.shared.cs diff --git a/src/CommunityToolkit.Maui/Primitives/StatusBarBehaviorDefaults.shared.cs b/src/CommunityToolkit.Maui/Primitives/Defaults/StatusBarBehaviorDefaults.shared.cs similarity index 100% rename from src/CommunityToolkit.Maui/Primitives/StatusBarBehaviorDefaults.shared.cs rename to src/CommunityToolkit.Maui/Primitives/Defaults/StatusBarBehaviorDefaults.shared.cs diff --git a/src/CommunityToolkit.Maui/Primitives/Defaults/TextValidationBehaviorDefaults.cs b/src/CommunityToolkit.Maui/Primitives/Defaults/TextValidationBehaviorDefaults.cs new file mode 100644 index 0000000000..f7dfd5eb99 --- /dev/null +++ b/src/CommunityToolkit.Maui/Primitives/Defaults/TextValidationBehaviorDefaults.cs @@ -0,0 +1,13 @@ +using System.Text.RegularExpressions; +using CommunityToolkit.Maui.Behaviors; + +namespace CommunityToolkit.Maui; + +static class TextValidationBehaviorDefaults +{ + public const int MinimumLength = 0; + public const int MaximumLength = int.MaxValue; + public const TextDecorationFlags DecorationFlags = TextDecorationFlags.None; + public const string RegexPattern = ""; + public const RegexOptions RegexOptions = System.Text.RegularExpressions.RegexOptions.None; +} \ No newline at end of file diff --git a/src/CommunityToolkit.Maui/Primitives/Defaults/ValidationBehaviorDefaults.cs b/src/CommunityToolkit.Maui/Primitives/Defaults/ValidationBehaviorDefaults.cs new file mode 100644 index 0000000000..0eb8df23b0 --- /dev/null +++ b/src/CommunityToolkit.Maui/Primitives/Defaults/ValidationBehaviorDefaults.cs @@ -0,0 +1,16 @@ +using CommunityToolkit.Maui.Behaviors; + +namespace CommunityToolkit.Maui; + +static class ValidationBehaviorDefaults +{ + public const bool IsNotValid = false; + public const bool IsValid = true; + public const bool IsRunning = false; + public const Style? ValidStyle = null; + public const Style? InvalidStyle = null; + public const object? Value = null; + + public static string ValuePropertyName { get; } = Entry.TextProperty.PropertyName; + public static ValidationFlags Flags { get; } = ValidationFlags.ValidateOnUnfocused | ValidationFlags.ForceMakeValidWhenFocused; +} \ No newline at end of file