谁能向我解释如何使用 Func<T, T, bool>? validateValue = null) Xamarin 社区工具包 ObservableObject 中的验证?

问题描述

我根本找不到这方面的任何示例。

这是我目前正在做的事情:

public partial class RenameGroupPopupviewmodel
{
    private string _newGroupName;

    public string NewGroupName
    {
        get => _newGroupName;
        set => SetProperty(ref _newGroupName,value);
    }
}

在 ObservableObject.cs 中有一个参数 validateValue 但我不知道也不明白如何使用它。

我想尝试使用 Func? validateValue = null) 调用一个名为 ValidateName 的方法,该方法将检查该值是否设置为“认”,如果是,则返回 false 以便不设置该值。

这是该类的完整代码

ObservableObject.cs

这是来自

代码片段
    /// <summary>
    /// Sets the property.
    /// </summary>
    /// <returns><c>true</c>,if property was set,<c>false</c> otherwise.</returns>
    /// <param name="backingStore">backing store.</param>
    /// <param name="value">Value.</param>
    /// <param name="validateValue">Validates value.</param>
    /// <param name="propertyName">Property name.</param>
    /// <param name="onChanged">On changed.</param>
    /// <typeparam name="T">The 1st type parameter.</typeparam>
    protected virtual bool SetProperty<T>(
        ref T backingStore,T value,[CallerMemberName] string propertyName = "",Action? onChanging = null,Action? onChanged = null,Func<T,T,bool>? validateValue = null)
    {
        // if value didn't change
        if (EqualityComparer<T>.Default.Equals(backingStore,value))
            return false;

        // if value changed but didn't validate
        if (validateValue != null && !validateValue(backingStore,value))
            return false;

        onChanging?.Invoke();
        backingStore = value;
        onChanged?.Invoke();
        OnPropertyChanged(propertyName);
        return true;
    }

我意识到我必须为验证提供一个函数,但我不确定如何指定它,它应该是一种普通的方法还是委托?这是我需要的功能

    private bool ValidateName(string groupName)
    {
        if (groupName == "default")
            return false;
        else
            return true;
    }

解决方法

您正在调用的方法包含此子句:

// if value changed but didn't validate
if (validateValue != null && !validateValue(backingStore,value))
    return false;

这是调用传入的 validateValue 委托。委托接受两个参数,这两个参数都是 T 类型的泛型 SetProperty<T>() 方法,并返回一个 bool,其中 false 表示传递给委托的值不符合调用者为委托实现的任何条件。

请注意,backingStore(属性的当前值)和 value(分配给属性的新值)都传递给验证委托。因此,委托人可以根据需要自由使用其中一个或两个。

您选择的方法似乎只关心新分配的值。因此,您可以通过更改验证方法签名以接受两个参数并忽略第一个参数来传递适当的委托:

private bool ValidateName(string currentName,string newName)
{
    if (newName == "default")
        return false;
    else
        return true;
}

public string NewGroupName
{
    get => _newGroupName;
    set => SetProperty(ref _newGroupName,value,validateValue: ValidateName);
}

或者你可以保留你的方法现在的样子,并将对它的调用包装在一个 lambda 表达式中:

public string NewGroupName
{
    get => _newGroupName;
    set => SetProperty(ref _newGroupName,validateValue: (_,newName) => ValidateName(newValue));
}

任何一个都可以。

请注意命名参数的使用,因为在传递的 value 参数和传递的委托引用之间还有其他参数,您可能仍然不想指定这些参数。命名 validateValue 参数允许仍然省略其他参数,导致它们的默认值按预期传递。

还要注意,在任何一种情况下,委托实例都是实际传递的内容。 C# 编译器自动将表达式(如第一个示例中的“方法组名称”或第二个示例中的“lambda 表达式”)转换为实例化新委托实例的代码,使用提供的方法作为目标的委托,根据代码的上下文推断委托类型(在此示例中,实际传递的委托类型将为 Func<string,string,bool>)。这种形式的 Lambda 表达式被编译为“匿名方法”。如果您愿意,您可以查找这些术语以获取更多信息。