dotnet icon indicating copy to clipboard operation
dotnet copied to clipboard

Add source generation: "NotifyDataErrorInfoFor"

Open mikechristiansenvae opened this issue 2 years ago • 0 comments

Overview

We already have the [NotifyDataErrorInfo] attribute, which adds source generation to validate this property.

But since we can use custom validation methods to perform multi-property validation, we should have a way to indicate that Property A influences the validation of Property B.

API breakdown

Add an attribute, NotifyDataErrorInfoForAttribute, which influences the source generator to add validation of other properties.

Right now, the generated setter for a property with [NotifyDataErrorInfo] looks like this:

if (!global::System.Collections.Generic.EqualityComparer<string?>.Default.Equals(path, value))
{
	OnPathChanging(value);
	OnPathChanging(default, value);
	OnPropertyChanging(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangingArgs.Path);
	path = value;
	ValidateProperty(value, "Path");
	OnPathChanged(value);
	OnPathChanged(default, value);
	OnPropertyChanged(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangedArgs.Path);
}

After the change, it would look like this:

if (!global::System.Collections.Generic.EqualityComparer<string?>.Default.Equals(path, value))
{
	OnPathChanging(value);
	OnPathChanging(default, value);
	OnPropertyChanging(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangingArgs.Path);
	path = value;
	ValidateProperty(value, "Path");
        ValidateProperty(SomeOtherProperty,"SomeOtherProperty");  // <---- THIS LINE IS NEW
	OnPathChanged(value);
	OnPathChanged(default, value);
	OnPropertyChanged(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangedArgs.Path);
}

Usage example


[NotifyDataErrorInfoFor(nameof(Path))]  // <--- NEW ATTRIBUTE
private bool isRequired;

[ObservableProperty]
[NotifyDataErrorInfo]
[CustomValidation(typeof(FileSystemLocationViewModel), nameof(ValidatePath))]
private string? path;

public static ValidationResult? ValidatePath(string? path, ValidationContext context)
{
    var instance = (FileSystemLocationViewModel)context.ObjectInstance;
    if (string.IsNullOrWhiteSpace(path))
    {
        if (instance.IsRequired)
            return new ValidationResult("Path is required");
        return ValidationResult.Success;
    }
    if(IsValidPath(path))
        return ValidationResult.Success;
    return new ValidationResult("Invalid path provided");
}

Breaking change?

No

Alternatives

Workaround (available now):

Manually implement the property

private bool isRequired;
public bool IsRequired
{
    get => this.isRequired;
    set
    {
        if (this.SetProperty(ref this.isRequired, value))
            this.ValidateProperty(this.Path, nameof(this.Path));
    }
}

Additional context

No response

Help us help you

No, just wanted to propose this

mikechristiansenvae avatar Nov 03 '23 15:11 mikechristiansenvae