ReactiveUI.Validation    4.0.9 
                            
                                 前缀已保留
                    dotnet add package ReactiveUI.Validation --version 4.0.9
NuGet\Install-Package ReactiveUI.Validation -Version 4.0.9
<PackageReference Include="ReactiveUI.Validation" Version="4.0.9" />
paket add ReactiveUI.Validation --version 4.0.9
#r "nuget: ReactiveUI.Validation, 4.0.9"
// Install ReactiveUI.Validation as a Cake Addin #addin nuget:?package=ReactiveUI.Validation&version=4.0.9 // Install ReactiveUI.Validation as a Cake Tool #tool nuget:?package=ReactiveUI.Validation&version=4.0.9
<a href="https://github.com/reactiveui/ReactiveUI.Validation"> <img width="140" heigth="140" src="https://github.com/reactiveui/ReactiveUI.Validation/blob/main/media/logo.png"> </a>
ReactiveUI.Validation
基于ReactiveUI的解决方案验证,以响应式的方式工作。 ReactiveUI.Validation最初由@jcmm33作为Vistian.Reactive.Validation开发,然后由Àlex Martínez Morón和ReactiveUI核心团队重构和更新。ReactiveUI.Validation支持所有平台,包括.NET Framework、.NET Standard、.NET Core、Maui。
NuGet包
将以下包安装到您的类库和一个特定平台项目中。
| 平台 | ReactiveUI包 | NuGet | 
|---|---|---|
| 任何平台 | ReactiveUI.Validation | |
| AndroidX (Maui, Xamarin) | ReactiveUI.Validation.AndroidX | |
| Xamarin.Android | ReactiveUI.Validation.AndroidSupport | 
使用方法
- 对于需要验证的ViewModel,实现IValidatableViewModel。
- 使用ValidationRule扩展方法在ViewModel中添加验证规则。
- 通过BindValidation或INotifyDataErrorInfo将视图绑定到验证规则。
示例
- 使用包含单个成员ValidationContext的IValidatableViewModel装饰现有的ViewModel。ValidationContext包含围绕ViewModel验证的所有功能。大多数对验证规则规范的访问是通过IValidatableViewModel接口上的扩展方法完成的。然后,向ViewModel添加验证。
using ReactiveUI.Validation.Extensions;
public class SampleViewModel : ReactiveObject, IValidatableViewModel
{
    public SampleViewModel()
    {
        // Creates the validation for the Name property.
        this.ValidationRule(
            viewModel => viewModel.Name,
            name => !string.IsNullOrWhiteSpace(name),
            "You must specify a valid name");
    }
    public ValidationContext ValidationContext { get; } = new ValidationContext();
    private string _name;
    public string Name
    {
        get => _name;
        set => this.RaiseAndSetIfChanged(ref _name, value);
    }
}
对于更复杂的验证场景,还有更多基于ValidationRule扩展方法的重载,这些方法接受可观察对象。这允许异步进行验证,并允许将复杂的可观察对象链组合以生成验证结果。
最简单的接受一个IObservable,其中观察到的布尔值指示ValidationRule是否有效。重载接受一个消息,当可观察对象产生一个false(无效)结果时使用。
IObservable<bool> passwordsObservable =
    this.WhenAnyValue(
        x => x.Password,
        x => x.ConfirmPassword,
        (password, confirmation) => password == confirmation);
this.ValidationRule(
    vm => vm.ConfirmPassword,
    passwordsObservable,
    "Passwords must match.");
可以使用接受任意IObservable事件流的扩展方法重载使用现有的任何可观察对象来驱动ValidationRule。重载接受一个自定义验证函数,该函数接受最新的TState,以及一个自定义错误消息函数,负责格式化最新的TState对象。该语法如下所示
// IObservable<{ Password, Confirmation }>
var passwordsObservable =
    this.WhenAnyValue(
        x => x.Password,
        x => x.ConfirmPassword,
        (password, confirmation) =>
            new { Password = password, Confirmation = confirmation });
this.ValidationRule(
    vm => vm.ConfirmPassword,
    passwordsObservable,
    state => state.Password == state.Confirmation,
    state => $"Passwords must match: {state.Password} != {state.Confirmation}");
注意 提取消息(messageFunc)的函数仅在确定有效性(isValidFunc)返回
false时调用,否则将消息设置为string.Empty。
最后,您可以直接提供一个流任何实现了IValidationState的对象(或结构)的可观察对象;或者您可以使用已实现该接口的ValidationState基类。由于结果对象直接存储在上下文中而没有进一步转换,这可能是最高效的方法
IObservable<IValidationState> usernameNotEmpty =
    this.WhenAnyValue(x => x.UserName)
        .Select(name => string.IsNullOrEmpty(name) 
            ? new ValidationState(false, "The username must not be empty")
            : ValidationState.Valid);
this.ValidationRule(vm => vm.UserName, usernameNotEmpty);
注意 由于有效的
ValidationState实际上不需要消息,因此有一个单例ValidationState.Valid属性,鼓励您在任何可能的情况下使用,以减少内存分配。
- 将验证呈现添加到视图。
using ReactiveUI.Validation.Extensions;
public class SampleView : ReactiveContentPage<SampleViewModel>
{
    public SampleView()
    {
        InitializeComponent();
        this.WhenActivated(disposables =>
        {
            this.Bind(ViewModel, vm => vm.Name, view => view.Name.Text)
                .DisposeWith(disposables);
            // Bind any validations that reference the Name property 
            // to the text of the NameError UI control.
            this.BindValidation(ViewModel, vm => vm.Name, view => view.NameError.Text)
                .DisposeWith(disposables);
            // Bind any validations attached to this particular view model
            // to the text of the FormErrors UI control.
            this.BindValidation(ViewModel, view => view.FormErrors.Text)
                .DisposeWith(disposables);
        });
    }
}
注意
Name是一个<Entry>,NameError是一个<Label>,而FormErrors也是一个<Label>。所有这些控件均来自Xamarin.Forms库。
使用Android扩展的示例
为Xamarin.Android及其材料设计控件TextInputLayout提供了扩展方法。这些扩展内部使用TextInputLayout控件中的Error属性,允许您实现显示验证错误的完全原生行为。要使用这些扩展,您必须导入ReactiveUI.Validation.Extensions并安装ReactiveUI.Validation.AndroidSupport或ReactiveUI.Validation.AndroidX
dotnet add package ReactiveUI.Validation.AndroidX
注意 在 ReactiveUI.Validation 1.7 及更低版本 中,针对 Android 的扩展存在于 主包中,目标为
MonoAndroid90,您不需要安装ReactiveUI.Validation.AndroidSupport。在 ReactiveUI.Validation 1.7 及更低版本 中,使用using ReactiveUI.Validation.Platforms.Android代替using ReactiveUI.Validation.Extensions。
<img src="https://user-images.githubusercontent.com/6759207/96716730-15729480-13ae-11eb-928e-7e408b7ffac4.png" width="400" />
// This using directive makes Android-specific extensions available.
// Make sure to install either the ReactiveUI.Validation.AndroidSupport
// package or the ReactiveUI.Validation.AndroidX package.
using ReactiveUI.Validation.Extensions;
public class SignUpActivity : ReactiveAppCompatActivity<SignUpViewModel>
{
    // The Android native text boxes declared in an .axml file.
    public TextInputEditText Password { get; set; }
    public TextInputEditText ConfirmPassword { get; set; }
    // The layouts wrapping the text boxes declared in an .axml file.
    public TextInputLayout PasswordField { get; set; }
    public TextInputLayout ConfirmPasswordField { get; set; }
    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate(bundle);
        SetContentView(Resource.Layout.Main);
        // The WireUpControls method is a magic ReactiveUI utility method for Android, see:
        // https://www.reactiveui.net/docs/handbook/data-binding/xamarin-android/wire-up-controls
        this.WireUpControls();
        this.Bind(ViewModel, x => x.Password, x => x.Password.Text);
        this.Bind(ViewModel, x => x.ConfirmPassword, x => x.ConfirmPassword.Text);
        // Bind any validations which reference the Password property 
        // to the Error property of the TextInputLayout control.
        this.BindValidation(ViewModel, x => x.Password, PasswordField);
        this.BindValidation(ViewModel, x => x.ConfirmPassword, ConfirmPasswordField);
    }
}
INotifyDataErrorInfo 支持
对于支持 INotifyDataErrorInfo 接口的平台,ReactiveUI.Validation 提供了一个名为 ReactiveValidationObject 的辅助基类。这个辅助类实现了 IValidatableViewModel 接口和 INotifyDataErrorInfo 接口。它监听 ValidationContext 的任何更改,并调用 INotifyDataErrorInfo 事件。
<img width="400" src="https://user-images.githubusercontent.com/6759207/96717163-bbbe9a00-13ae-11eb-8c54-89cd339cbd5c.png">
using ReactiveUI.Validation.Extensions;
public class SampleViewModel : ReactiveValidationObject
{
    public SampleViewModel()
    {
        this.ValidationRule(
            viewModel => viewModel.Name, 
            name => !string.IsNullOrWhiteSpace(name),
            "Name shouldn't be null or white space.");
    }
    private string _name = string.Empty;
    public string Name
    {
        get => _name;
        set => this.RaiseAndSetIfChanged(ref _name, value);
    }
}
注意 请记住,
INotifyDataErrorInfo仅通过 XAML 绑定支持。ReactiveUI 绑定不使用 WPF 的内建类。
当使用接受 observable 的 ValidationRule 重载时,请记住将验证规则要针对的属性作为第一个参数提供。否则,INotifyDataErrorInfo 就不能确定错误消息是针对哪个属性的。
this.ValidationRule(
    vm => vm.ConfirmPassword,
    passwordsObservable,
    "Passwords must match.");
自定义格式化程序
如果您想覆盖验证库中使用默认的 SingleLineFormatter,可以将 IValidationTextFormatter<T> 的实例传递给 BindValidation 调用。默认的 SingleLineFormatter 接受一个分隔符字符,默认使用空白符,所以下面的代码片段显示了如何使用非默认分隔符字符。
// This formatter is based on the default SingleLineFormatter but uses a custom separator char.
var formatter = new SingleLineFormatter(Environment.NewLine);
this.BindValidation(ViewModel, x => x.ErrorLabel.Text, formatter)
    .DisposeWith(disposables);
最简单的自定义 IValidationTextFormatter<TOut> 实现可能如下所示。
private class ConstFormatter : IValidationTextFormatter<string>
{
    private readonly string _text;
    public ConstFormatter(string text = "The input is invalid.") => _text = text;
    public string Format(ValidationText validationText) => _text;
}
// This formatter is based on a custom IValidationTextFormatter implementation.
var formatter = new ConstFormatter("The input is invalid.");
this.BindValidation(ViewModel, x => x.ErrorLabel.Text, formatter)
    .DisposeWith(disposables);
如果您想覆盖 ReactiveUI.Validation 默认使用的 IValidationTextFormatter<string>,请在您的应用程序开始之前将 IValidationTextFormatter<string> 的实例注册到 Locator.CurrentMutable 中。这可以在您的应用程序需要本地化且您希望将消息键而不是消息传递给 ValidationRule 调用的情况下很有用。
// Register a singleton instance of IValidationTextFormatter<string> into Splat.Locator.
Locator.CurrentMutable.RegisterConstant(new CustomFormatter(), typeof(IValidationTextFormatter<string>));
功能
本质上,ReactiveUI Validation 是一个相对简单的 ValidationContext 模型,其中包含一系列 IValidationComponent 实例。一个 IValidationComponent 提供了一个 IValidationState 的可观察序列。每当验证状态发生变化(无论是有效性状态的转换还是 ValidationText 的更改)时,就会推送一个新的值。
- 规则可以由单个或多个属性以及更通用的 Observables 组成。
- 验证文本可以封装有效和无效状态。
- 绑定可以发生到视图或动作。
- 验证文本可以引用 ViewModel 或构成验证规则的属性,例如包含作为验证消息一部分输入的文本。
- 可以通过自定义格式化程序调整验证文本输出,不仅允许单行和的多行输出,也允许在 Android 这样的平台上实现更丰富的渲染,例如粗体/斜体。
反馈
请通过 GitHub issues 提出问题、评论或错误报告。
贡献
ReactiveUI Validation 在 OSI 批准的开源许可证下开发,使其可以自由使用和分发,甚至可以用于商业用途。我们热爱参与这个项目的每一个人,并希望您也加入我们,尤其是如果您刚刚开始或从未为开源项目贡献过。
所以,为了你,亲爱的希望加入我们的人——这是您如何支持我们的方法
- 回答 StackOverflow 上的问题
- 传授知识和教育新一代的开发者
- 在您认为适合或缺乏的地方提交文档更新。
- 对代码库做出贡献。
版权和许可证
代码根据MIT许可协议发布。
| 产品 | 版本 兼容和额外的计算目标框架版本。 | 
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net6.0-windows10.0.17763 is compatible. net7.0 is compatible. net7.0-android was computed. net7.0-android33.0 is compatible. net7.0-ios was computed. net7.0-ios16.1 is compatible. net7.0-maccatalyst was computed. net7.0-maccatalyst16.1 is compatible. net7.0-macos was computed. net7.0-macos13.0 is compatible. net7.0-tvos was computed. net7.0-tvos16.1 is compatible. net7.0-windows was computed. net7.0-windows10.0.17763 is compatible. net8.0 is compatible. net8.0-android was computed. net8.0-android34.0 is compatible. net8.0-browser was computed. net8.0-ios was computed. net8.0-ios17.2 is compatible. net8.0-maccatalyst was computed. net8.0-maccatalyst17.2 is compatible. net8.0-macos was computed. net8.0-macos14.2 is compatible. net8.0-tvos was computed. net8.0-tvos17.2 is compatible. net8.0-windows was computed. net8.0-windows10.0.17763 is compatible. | 
| .NET Core | netcoreapp2.0 已计算。 netcoreapp2.1 已计算。 netcoreapp2.2 已计算。 netcoreapp3.0 已计算。 netcoreapp3.1 已计算。 | 
| .NET Standard | netstandard2.0 兼容。 netstandard2.1 已计算。 | 
| .NET Framework | net461 已计算。 net462 兼容。 net463 已计算。 net47 已计算。 net471 已计算。 net472 兼容。 net48 已计算。 net481 已计算。 | 
| MonoAndroid | monoandroid 已计算。 | 
| MonoMac | monomac 已计算。 | 
| MonoTouch | monotouch 已计算。 | 
| Tizen | tizen40 已计算。 tizen60 已计算。 | 
| Xamarin.iOS | xamarinios 已计算。 | 
| Xamarin.Mac | xamarinmac 已计算。 | 
| Xamarin.TVOS | xamarintvos 已计算。 | 
| Xamarin.WatchOS | xamarinwatchos 已计算。 | 
- 
                                                    .NETFramework 4.6.2- ReactiveUI (>= 20.0.1)
- System.Collections.Immutable (>= 8.0.0)
 
- 
                                                    .NETFramework 4.7.2- ReactiveUI (>= 20.0.1)
- System.Collections.Immutable (>= 8.0.0)
 
- 
                                                    .NETStandard 2.0- ReactiveUI (>= 20.0.1)
- System.Collections.Immutable (>= 8.0.0)
 
- 
                                                    net6.0- ReactiveUI (>= 20.0.1)
 
- 
                                                    net6.0-windows10.0.17763- ReactiveUI (>= 20.0.1)
 
- 
                                                    net7.0- ReactiveUI (>= 20.0.1)
 
- 
                                                    net7.0-android33.0- ReactiveUI (>= 20.0.1)
 
- 
                                                    net7.0-ios16.1- ReactiveUI (>= 20.0.1)
 
- 
                                                    net7.0-maccatalyst16.1- ReactiveUI (>= 20.0.1)
 
- 
                                                    net7.0-macos13.0- ReactiveUI (>= 20.0.1)
 
- 
                                                    net7.0-tvos16.1- ReactiveUI (>= 20.0.1)
 
- 
                                                    net7.0-windows10.0.17763- ReactiveUI (>= 20.0.1)
 
- 
                                                    net8.0- ReactiveUI (>= 20.0.1)
 
- 
                                                    net8.0-android34.0- ReactiveUI (>= 20.0.1)
 
- 
                                                    net8.0-ios17.2- ReactiveUI (>= 20.0.1)
 
- 
                                                    net8.0-maccatalyst17.2- ReactiveUI (>= 20.0.1)
 
- 
                                                    net8.0-macos14.2- ReactiveUI (>= 20.0.1)
 
- 
                                                    net8.0-tvos17.2- ReactiveUI (>= 20.0.1)
 
- 
                                                    net8.0-windows10.0.17763- ReactiveUI (>= 20.0.1)
 
NuGet包 (11)
显示依赖于ReactiveUI.Validation的前5个NuGet包
| 包 | 下载 | 
|---|---|
| Zafiro.UI Zafiro 客户端交互完美性 | |
| ArtemisRGB.UI.shared 包描述 | |
| Zafiro.Avalonia.FileExplorer 包描述 | |
| KH.UIBase InstrumentBaseLib | |
| Acorisoft.Island Island 设计语言(预览版) | 
GitHub 仓库 (16)
显示依赖 ReactiveUI.Validation 的最受欢迎的 5 个 GitHub 仓库
| 仓库 | 星标 | 
|---|---|
| 2dust/v2rayN 
                                                            适用于 Windows 的图形客户端,支持 Xray 内核、v2fly 内核等
                                                         | |
| shadowsocks/shadowsocks-windows 
                                                            shadowsocks 的 C# 版本
                                                         | |
| AvaloniaUI/Avalonia 
                                                            使用 C# 和 XAML 开发桌面、嵌入式、移动和 WebAssembly 应用。最受欢迎的 .NET UI 客户端技术
                                                         | |
| 2dust/clashN 
                                                            适用于 Windows 的 Clash 客户端,支持米漫游
                                                         | |
| Artemis-RGB/Artemis 
                                                            为许多品牌 RGB 外围设备提供先进的统一灯光
                                                         | 
| 版本 | 下载 | 上次更新 | 
|---|---|---|
| 4.0.9 | 8,112 | 5/11/2024 | 
| 4.0.6 | 446 | 5/7/2024 | 
| 3.1.7 | 88,108 | 2/1/2023 | 
| 3.0.22 | 51,563 | 11/25/2022 | 
| 3.0.1 | 28,936 | 6/28/2022 | 
| 2.2.1 | 63,506 | 9/29/2021 | 
| 2.1.1 | 54,104 | 1/22/2021 | 
| 2.0.1 | 4,046 | 12/13/2020 | 
| 1.8.6 | 12,162 | 10/22/2020 | 
| 1.8.1 | 1,094 | 10/19/2020 | 
| 1.7.1 | 1,729 | 10/15/2020 | 
| 1.6.4 | 1,099 | 10/12/2020 | 
| 1.5.5 | 6,113 | 7/28/2020 | 
| 1.5.3 | 1,117 | 7/26/2020 | 
| 1.4.15 | 15,287 | 5/7/2020 | 
| 1.4.13 | 4,906 | 4/1/2020 | 
| 1.4.10 | 9,069 | 1/31/2020 | 
| 1.4.8 | 1,043 | 1/31/2020 | 
| 1.4.7 | 2,147 | 1/14/2020 | 
| 1.4.6 | 1,666 | 12/26/2019 | 
| 1.4.1 | 11,543 | 9/21/2019 | 
| 1.3.1 | 966 | 9/21/2019 | 
| 1.2.1 | 8,343 | 5/13/2019 | 
| 1.1.1 | 13,763 | 5/7/2019 | 
| 1.0.13 | 1,221 | 4/1/2019 | 
| 1.0.3 | 1,289 | 2/26/2019 | 
| 1.0.2 | 999 | 2/26/2019 | 
| 1.0.0 | 1,353 | 7/26/2020 |