/// <summary>
        /// Binding a specified view model property to a provided action.
        /// </summary>
        /// <typeparam name="TView"></typeparam>
        /// <typeparam name="TViewModel"></typeparam>
        /// <typeparam name="TViewModelProperty1"></typeparam>
        /// <typeparam name="TOut"></typeparam>
        /// <param name="view"></param>
        /// <param name="viewModelProperty"></param>
        /// <param name="action"></param>
        /// <param name="formatter"></param>
        /// <param name="strict"></param>
        /// <returns></returns>
        public static IValidationBinding ForProperty <TView, TViewModel, TViewModelProperty1, TOut>(TView view,
                                                                                                    Expression <Func <TViewModel, TViewModelProperty1> > viewModelProperty,
                                                                                                    Action <ValidationState, TOut> action,
                                                                                                    IValidationTextFormatter <TOut> formatter = null,
                                                                                                    bool strict = true)
            where TView : IViewFor <TViewModel>
            where TViewModel : ReactiveObject, ISupportsValidation
        {
            if (formatter == null)
            {
                throw new ArgumentNullException(nameof(formatter));
            }

            var vcObs = view.WhenAnyValue(v => v.ViewModel).
                        Where(vm => vm != null).
                        Select(
                viewModel =>
                viewModel.ValidationContext.ResolveFor(viewModelProperty, strict)
                .ValidationStatusChange).
                        Switch().
                        Select(vc => new { ValidationChange = vc, Formatted = formatter.Format(vc.Text) }).
                        Do(r => action(r.ValidationChange, r.Formatted)).
                        Select(_ => Unit.Default);

            return(new ValidationBinding(vcObs));
        }
Example #2
0
        /// <summary>
        /// Create a binding between a view model property and a view property.
        /// </summary>
        /// <remarks>Supports multiple validations for the same property.</remarks>
        /// <typeparam name="TView">ViewFor of ViewModel type.</typeparam>
        /// <typeparam name="TViewModel">ViewModel type.</typeparam>
        /// <typeparam name="TViewModelProperty">ViewModel property type.</typeparam>
        /// <typeparam name="TViewProperty">View property type.</typeparam>
        /// <param name="view">View instance.</param>
        /// <param name="viewModelProperty">ViewModel property.</param>
        /// <param name="viewProperty">View property.</param>
        /// <param name="formatter">Validation formatter.</param>
        /// <param name="strict">Indicates if the ViewModel property to find is unique.</param>
        /// <returns>Returns a validation component.</returns>
        public static IValidationBinding ForProperty <TView, TViewModel, TViewModelProperty, TViewProperty>(
            TView view,
            Expression <Func <TViewModel, TViewModelProperty> > viewModelProperty,
            Expression <Func <TView, TViewProperty> > viewProperty,
            IValidationTextFormatter <string> formatter = null,
            bool strict = true)
            where TView : IViewFor <TViewModel>
            where TViewModel : ReactiveObject, ISupportsValidation
        {
            if (formatter == null)
            {
                formatter = SingleLineFormatter.Default;
            }

            var vcObs = view.WhenAnyValue(v => v.ViewModel)
                        .Where(vm => vm != null)
                        .Select(
                viewModel => viewModel.ValidationContext
                .ResolveForMultiple(viewModelProperty, strict)
                .Select(x => x.ValidationStatusChange)
                .CombineLatest())
                        .Switch()
                        .Select(states => states.Select(state => formatter.Format(state.Text)).ToList());

            var updateObs = BindToView(vcObs, view, viewProperty)
                            .Select(_ => Unit.Default);

            return(new ValidationBindingEx(updateObs));
        }
        /// <summary>
        /// Bind a <see cref="ValidationHelper"/> to a specified action.
        /// </summary>
        /// <typeparam name="TView"></typeparam>
        /// <typeparam name="TViewModel"></typeparam>
        /// <typeparam name="TOut"></typeparam>
        /// <param name="view"></param>
        /// <param name="viewModelHelperProperty"></param>
        /// <param name="action"></param>
        /// <param name="formatter"></param>
        /// <returns></returns>
        public static IValidationBinding ForValidationHelperProperty <TView, TViewModel, TOut>(TView view,
                                                                                               Expression <Func <TViewModel, ValidationHelper> > viewModelHelperProperty,
                                                                                               Action <ValidationState, TOut> action,
                                                                                               IValidationTextFormatter <TOut> formatter = null
                                                                                               )
            where TView : IViewFor <TViewModel>
            where TViewModel : ReactiveObject, ISupportsValidation
        {
            if (formatter == null)
            {
                throw new ArgumentNullException(nameof(formatter));
            }

            var vcObs = view.WhenAnyValue(v => v.ViewModel).
                        Where(vm => vm != null).
                        Select(
                viewModel =>
                viewModel.WhenAnyValue(viewModelHelperProperty).SelectMany(vy => vy.ValidationChanged)).
                        Switch().
                        Select(vc => new { ValidationChange = vc, Formatted = formatter.Format(vc.Text) });

            var updateObs = vcObs.Do(r =>
            {
                action(r.ValidationChange, r.Formatted);
            }).
                            Select(_ => Unit.Default);

            return(new ValidationBinding(updateObs));
        }
        /// <summary>
        /// Create a binding between a <see cref="ValidationHelper"/> and a specified view property.
        /// </summary>
        /// <typeparam name="TView"></typeparam>
        /// <typeparam name="TViewModel"></typeparam>
        /// <typeparam name="TViewProperty"></typeparam>
        /// <param name="view"></param>
        /// <param name="viewModelHelperProperty"></param>
        /// <param name="viewProperty"></param>
        /// <param name="formatter"></param>
        /// <returns></returns>
        public static IValidationBinding ForValidationHelperProperty <TView, TViewModel, TViewProperty>(TView view,
                                                                                                        Expression <Func <TViewModel, ValidationHelper> > viewModelHelperProperty,
                                                                                                        Expression <Func <TView, TViewProperty> > viewProperty,
                                                                                                        IValidationTextFormatter <string> formatter = null)
            where TView : IViewFor <TViewModel>
            where TViewModel : ReactiveObject, ISupportsValidation

        {
            if (formatter == null)
            {
                formatter = SingleLineFormatter.Default;
            }

            var vcObs = view.WhenAnyValue(v => v.ViewModel).
                        Where(vm => vm != null).
                        Select(
                viewModel =>
                viewModel.WhenAnyValue(viewModelHelperProperty).SelectMany(vy => vy.ValidationChanged)).
                        Switch().
                        Select(vc => formatter.Format(vc.Text));

            var updateObs = BindToView(vcObs, view, viewProperty).
                            Select(_ => Unit.Default);

            return(new ValidationBinding(updateObs));
        }
        /// <summary>
        /// Creates a binding between a ViewModel and a View property.
        /// </summary>
        /// <typeparam name="TView">ViewFor of ViewModel type.</typeparam>
        /// <typeparam name="TViewModel">ViewModel type.</typeparam>
        /// <typeparam name="TViewProperty">View property type.</typeparam>
        /// <param name="view">View instance.</param>
        /// <param name="viewProperty">View property to bind the validation message.</param>
        /// <param name="formatter">Validation formatter.</param>
        /// <returns>Returns a validation component.</returns>
        public static IValidationBinding ForViewModel <TView, TViewModel, TViewProperty>(
            TView view,
            Expression <Func <TView, TViewProperty> > viewProperty,
            IValidationTextFormatter <string>?formatter = null)
            where TView : IViewFor <TViewModel>
            where TViewModel : ReactiveObject, IValidatableViewModel
        {
            if (view is null)
            {
                throw new ArgumentNullException(nameof(view));
            }

            if (viewProperty is null)
            {
                throw new ArgumentNullException(nameof(view));
            }

            formatter ??= SingleLineFormatter.Default;

            var vcObs = view
                        .WhenAnyValue(v => v.ViewModel)
                        .Where(vm => vm != null)
                        .SelectMany(vm => vm !.ValidationContext.ValidationStatusChange)
                        .Select(vc => formatter.Format(vc.Text));

            var updateObs = BindToView(vcObs, view, viewProperty)
                            .Select(_ => Unit.Default);

            return(new ValidationBinding(updateObs));
        }
        /// <summary>
        /// Creates a binding from a specified ViewModel property to a provided action.
        /// </summary>
        /// <typeparam name="TView">ViewFor of ViewModel type.</typeparam>
        /// <typeparam name="TViewModel">ViewModel type.</typeparam>
        /// <typeparam name="TViewModelProperty">ViewModel property type.</typeparam>
        /// <typeparam name="TOut">Action return type.</typeparam>
        /// <param name="view">View instance.</param>
        /// <param name="viewModelProperty">ViewModel property.</param>
        /// <param name="action">Action to be executed.</param>
        /// <param name="formatter">Validation formatter.</param>
        /// <param name="strict">Indicates if the ViewModel property to find is unique.</param>
        /// <returns>Returns a validation component.</returns>
        public static IValidationBinding ForProperty <TView, TViewModel, TViewModelProperty, TOut>(
            TView view,
            Expression <Func <TViewModel, TViewModelProperty> > viewModelProperty,
            Action <IList <ValidationState>, IList <TOut> > action,
            IValidationTextFormatter <TOut> formatter,
            bool strict = true)
            where TView : IViewFor <TViewModel>
            where TViewModel : ReactiveObject, IValidatableViewModel
        {
            if (view is null)
            {
                throw new ArgumentNullException(nameof(view));
            }

            if (viewModelProperty is null)
            {
                throw new ArgumentNullException(nameof(viewModelProperty));
            }

            if (action is null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            if (formatter == null)
            {
                throw new ArgumentNullException(nameof(formatter));
            }

            var vcObs = view
                        .WhenAnyValue(v => v.ViewModel)
                        .Where(vm => vm != null)
                        .Select(
                viewModel => viewModel !
                .ValidationContext
                .ResolveFor(viewModelProperty, strict)
                .Select(x => x.ValidationStatusChange)
                .CombineLatest())
                        .Switch()
                        .Select(states => new
            {
                ValidationChange = states,
                Formatted        = states
                                   .Select(state => formatter.Format(state.Text))
                                   .ToList()
            })
                        .Do(r => action(r.ValidationChange, r.Formatted))
                        .Select(_ => Unit.Default);

            return(new ValidationBinding(vcObs));
        }
        /// <summary>
        /// Creates a binding between a ViewModel property and a view property.
        /// </summary>
        /// <typeparam name="TView">ViewFor of ViewModel type.</typeparam>
        /// <typeparam name="TViewModel">ViewModel type.</typeparam>
        /// <typeparam name="TViewModelProperty">ViewModel property type.</typeparam>
        /// <typeparam name="TViewProperty">View property type.</typeparam>
        /// <param name="view">View instance.</param>
        /// <param name="viewModelProperty">ViewModel property.</param>
        /// <param name="viewProperty">View property.</param>
        /// <param name="formatter">Validation formatter. Defaults to the <see cref="SingleLineFormatter"/>.</param>
        /// <param name="strict">Indicates if the ViewModel property to find is unique.</param>
        /// <returns>Returns a validation component.</returns>
        public static IValidationBinding ForProperty <TView, TViewModel, TViewModelProperty, TViewProperty>(
            TView view,
            Expression <Func <TViewModel, TViewModelProperty> > viewModelProperty,
            Expression <Func <TView, TViewProperty> > viewProperty,
            IValidationTextFormatter <string>?formatter = null,
            bool strict = true)
            where TView : IViewFor <TViewModel>
            where TViewModel : ReactiveObject, IValidatableViewModel
        {
            if (view is null)
            {
                throw new ArgumentNullException(nameof(view));
            }

            if (viewModelProperty is null)
            {
                throw new ArgumentNullException(nameof(viewModelProperty));
            }

            if (viewProperty is null)
            {
                throw new ArgumentNullException(nameof(viewProperty));
            }

            formatter ??= SingleLineFormatter.Default;

            var vcObs = view
                        .WhenAnyValue(v => v.ViewModel)
                        .Where(vm => vm != null)
                        .Select(
                viewModel => viewModel !
                .ValidationContext
                .ResolveFor(viewModelProperty, strict)
                .Select(x => x.ValidationStatusChange)
                .CombineLatest())
                        .Switch()
                        .Select(
                states => states
                .Select(state => formatter.Format(state.Text))
                .FirstOrDefault(msg => !string.IsNullOrEmpty(msg)) ?? string.Empty);

            var updateObs = BindToView(vcObs, view, viewProperty)
                            .Select(_ => Unit.Default);

            return(new ValidationBinding(updateObs));
        }