首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ReactiveUi 5的验证

ReactiveUi 5的验证
EN

Stack Overflow用户
提问于 2013-09-17 14:02:59
回答 2查看 2K关注 0票数 2

我使用的是ReactiveUI 5,但现在我需要在ViewModel中进行验证,所以我使用了文档中描述的ReactiveValidatedObject。在版本4示例中,配置与tha相同,但似乎不起作用。运行示例代码运行良好,但在版本5中它不起作用,因此不会触发在ValidatesViaMethod属性中定义的验证方法。

我用一个简单的textbox验证来检查每件东西及其与示例代码相等的内容。

我不知道还有什么可以做的。还有其他方法可以用ReactiveUI进行验证吗?除了第4版之外,我找不到任何文档或示例来说明如何做到这一点。

这是我的ViewMode,我使用的是版本4的ReactiveValidatedObject和版本5的路由。

代码语言:javascript
复制
public class InputViewModel : ReactiveValidatedObject , IRoutableViewModel
{
    bool val;
    bool invalid = false;

    public InputViewModel(IScreen hostscreen)
    {            
        ValidationObservable.Subscribe(x => IsValid = this.IsObjectValid());                
        var whenAnyValuesChange = this.WhenAny(x => x.IsValid, x => x.Value);                       
        HostScreen = hostscreen ?? RxApp.DependencyResolver.GetService<IScreen>();
    }

    [ValidatesViaMethod(AllowBlanks = false, AllowNull = false, Name = "IsNameValid", ErrorMessage = "Favor informe o nome corretamente")]
    public string Name
    {
        get {  return _name; }
        set 
        {
            this.RaiseAndSetIfChanged(ref _name, value);
        }
    }

    public bool IsNameValid(string name)
    {
        return name.Length >= 2;
    }

    public IScreen HostScreen
    {
        get;
        private set;
    }

    public string UrlPathSegment
    {
        get { return "InputView"; }
    }

    public Simulation Simulation { get; set; }

    private bool _IsValid;
    public bool IsValid
    {
        get { return _IsValid; }
        set { this.RaiseAndSetIfChanged(ref _IsValid, value); }
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-10-22 14:16:40

如果您需要对验证进行更多的控制,我建议尝试一下FluentValidation。它很好地集成了任何MVVM框架,通过使用InlineValidator,您可以处理比基于属性的验证更复杂的验证场景。我自己也在我的大部分项目中使用它。

票数 1
EN

Stack Overflow用户

发布于 2019-08-06 10:06:04

如果您想将FluentValidationReactiveUI结合使用,您可以这样做:

Validator

代码语言:javascript
复制
public sealed class ContactViewModelValidator 
    : AbstractValidator<ContactViewModel>
{
    pulbic ContactViewModelValidator()
    {
        RuleFor(vm => vm.FirstName)
            .Required()
            .WithMessage("The first name is required");
        // more rules
    }
}

ViewModel

代码语言:javascript
复制
public sealed class ContactViewModel : ReactiveObject, ISupportsActivation
{
    public ViewModelActivator Activator { get; } = new ViewModelActivator();

    [Reactive] public string FirstName { get; set; }
    [Reactive] public string FirstNameErrorMessage { get; set; }

    // other properties

    private IValidator<ContactViewModel> Validator { get; }

    public ContactViewModel(IValidator<ContactViewModel> validator)
    {
        Validator = validator ?? throw new ArgumentNullException(nameof(validator));

         this.WhenActivated(d =>
         {
             ActivateValidation(this, d);

             // other activations
         });
    }

    // since this is static, you can put it in an external class
    private static void ActivateValidation(ContactViewModel viewModel, CompositeDisposable d)
    {
        var validationSubject = new Subject<ValidationResult>().DisposeWith(d);
        viewModel.WhenAnyValue(vm => vm.FirstName /* other properties */)
            .Select(_ => viewModel)
            .Select(viewModel.Validator.Validate)
            .ObserveOn(RxApp.MainThreadScheduler)
            .SubscribeOn(RxApp.MainThreadScheduler)
            .Subscribe(result => validationSubject.OnNext(result))
            .DisposeWith(d);

        validationSubject
            .Select(e => e.Errors)
            .ObserveOn(RxApp.MainThreadScheduler)
            .SubscribeOn(RxApp.MainThreadScheduler)
            .Subscribe(errors =>
            {
                using (viewModel.DelayChangeNotifications())
                {
                    viewModel.FirstNameErrorMessage = 
                        errors.GetMessageForProperty(nameof(viewModel.FirstName));

                    // handle other properties
                }
            })
            .DisposeWith(d);
    }
}

扩展

代码语言:javascript
复制
public static class ValidationFailureExtensions
{
    // This is an example that gives you all messages,
    // no matter if they are warnings or errors.
    // Provide your own implementation that fits your need.
    public static string GetMessageForProperty(this IList<ValidationFailure> errors, string propertyName)
    {
        return errors
            .Where(e => e.PropertyName == propertyName)
            .Select(e => e.ErrorMessage)
            .Aggregate(new StringBuilder(), (builder, s) => builder.AppendLine(s), builder => builder.ToString());
    }
}

视图

代码语言:javascript
复制
public partial class ContactControl : IViewFor<ContactViewModel>
{
    public ContactControl()
    {
        InitializeComponent();
    }

    object IViewFor.ViewModel
    {
        get => ViewModel;
        set => ViewModel = value as ContactViewModel;
    }

    public ContactViewModel ViewModel
    {
        get => DataContext as ContactiewModel;
        set => DataContext = value;
    }
}
代码语言:javascript
复制
d:DataContext="{d:DesignInstance Type=local:ContactViewModel, IsDesignTimeCreatable=True}" 
代码语言:javascript
复制
<UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="..." />
                <ResourceDictionary>
                    <Style BasedOn="{StaticResource {x:Type TextBlock}}" 
                           TargetType="TextBlock"
                           x:Key="ErrorMessageTextBlock">
                            <Style.Setters>
                                <Setter Property="Foreground" Value="Red" />
                                <Setter Property="Height" Value="Auto" />
                                <Setter Property="TextWrapping" Value="Wrap" />
                                <Setter Property="Padding" Value="4" />
                        </Style.Setters>
                            <Style.Triggers>
                                <Trigger Property="Text" Value="{x:Null}">
                                    <Setter Property="Height" Value="0" />
                                    <Setter Property="Visibility" Value="Collapsed" />
                                </Trigger>
                                <Trigger Property="Text" Value="">
                                    <Setter Property="Height" Value="0" />
                                    <Setter Property="Visibility" Value="Collapsed" />
                                </Trigger>
                            </Style.Triggers>
                    </Style>
                </ResourceDictionary>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>
代码语言:javascript
复制
<TextBlock Text="{Binding FirstNameErrorMessage}"
           Style="{StaticResource ErrorMessageTextBlock}" />
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18852065

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档