< Summary

Class:ReactiveUI.Validation.Extensions.ViewForExtensions
Assembly:ReactiveUI.Validation
File(s):D:\a\1\s\src\ReactiveUI.Validation\Extensions\ViewForExtensions.cs
Covered lines:11
Uncovered lines:34
Coverable lines:45
Total lines:230
Line coverage:24.4% (11 of 45)
Covered branches:8
Total branches:36
Branch coverage:22.2% (8 of 36)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
BindValidationEx(...)-0%0%
BindValidation(...)-57.14%50%
BindValidation(...)-60%50%
BindValidation(...)-57.14%50%
BindToDirect(...)-0%0%

File(s)

D:\a\1\s\src\ReactiveUI.Validation\Extensions\ViewForExtensions.cs

#LineLine coverage
 1// Copyright (c) 2020 .NET Foundation and Contributors. All rights reserved.
 2// Licensed to the .NET Foundation under one or more agreements.
 3// The .NET Foundation licenses this file to you under the MIT license.
 4// See the LICENSE file in the project root for full license information.
 5
 6using System;
 7using System.Diagnostics.CodeAnalysis;
 8using System.Linq.Expressions;
 9using System.Reactive.Linq;
 10using ReactiveUI.Validation.Abstractions;
 11using ReactiveUI.Validation.Formatters;
 12using ReactiveUI.Validation.Formatters.Abstractions;
 13using ReactiveUI.Validation.Helpers;
 14using ReactiveUI.Validation.ValidationBindings;
 15using Splat;
 16
 17namespace ReactiveUI.Validation.Extensions
 18{
 19    /// <summary>
 20    /// Extensions methods associated to <see cref="IViewFor"/> instances.
 21    /// </summary>
 22    [SuppressMessage("Roslynator", "RCS1163", Justification = "Needed for Expression context.")]
 23    public static class ViewForExtensions
 24    {
 25        /// <summary>
 26        /// Binds the specified ViewModel property validation to the View property.
 27        /// </summary>
 28        /// <remarks>Supports multiple validations for the same property.</remarks>
 29        /// <typeparam name="TView">IViewFor of TViewModel.</typeparam>
 30        /// <typeparam name="TViewModel">ViewModel type.</typeparam>
 31        /// <typeparam name="TViewModelProperty">ViewModel property type.</typeparam>
 32        /// <typeparam name="TViewProperty">View property type.</typeparam>
 33        /// <param name="view">IViewFor instance.</param>
 34        /// <param name="viewModel">ViewModel instance.</param>
 35        /// <param name="viewModelProperty">ViewModel property.</param>
 36        /// <param name="viewProperty">View property to bind the validation message.</param>
 37        /// <returns>Returns a <see cref="IDisposable"/> object.</returns>
 38        [Obsolete("This method is no longer required, BindValidation now supports multiple validations.")]
 39        [SuppressMessage("Design", "CA1801: Parameter unused", Justification = "Used for generic resolution")]
 40        public static IDisposable BindValidationEx<TView, TViewModel, TViewModelProperty, TViewProperty>(
 41            this TView view,
 42            TViewModel viewModel,
 43            Expression<Func<TViewModel, TViewModelProperty>> viewModelProperty,
 44            Expression<Func<TView, TViewProperty>> viewProperty)
 45            where TView : IViewFor<TViewModel>
 46            where TViewModel : ReactiveObject, IValidatableViewModel
 47        {
 048            if (viewModel is null)
 49            {
 050                throw new ArgumentNullException(nameof(viewModel));
 51            }
 52
 053            if (viewModelProperty is null)
 54            {
 055                throw new ArgumentNullException(nameof(viewModelProperty));
 56            }
 57
 058            if (viewProperty is null)
 59            {
 060                throw new ArgumentNullException(nameof(viewProperty));
 61            }
 62
 063            return ValidationBinding.ForProperty(view, viewModelProperty, viewProperty);
 64        }
 65
 66        /// <summary>
 67        /// Binds the specified ViewModel property validation to the View property.
 68        /// </summary>
 69        /// <typeparam name="TView">IViewFor of TViewModel.</typeparam>
 70        /// <typeparam name="TViewModel">ViewModel type.</typeparam>
 71        /// <typeparam name="TViewModelProperty">ViewModel property type.</typeparam>
 72        /// <typeparam name="TViewProperty">View property type.</typeparam>
 73        /// <param name="view">IViewFor instance.</param>
 74        /// <param name="viewModel">ViewModel instance.</param>
 75        /// <param name="viewModelProperty">ViewModel property.</param>
 76        /// <param name="viewProperty">View property to bind the validation message.</param>
 77        /// <param name="formatter">Validation formatter. Defaults to <see cref="SingleLineFormatter"/>.</param>
 78        /// <returns>Returns a <see cref="IDisposable"/> object.</returns>
 79        [SuppressMessage("Design", "CA1801: Parameter unused", Justification = "Used for generic resolution")]
 80        public static IDisposable BindValidation<TView, TViewModel, TViewModelProperty, TViewProperty>(
 81            this TView view,
 82            TViewModel viewModel,
 83            Expression<Func<TViewModel, TViewModelProperty>> viewModelProperty,
 84            Expression<Func<TView, TViewProperty>> viewProperty,
 85            IValidationTextFormatter<string>? formatter = null)
 86            where TView : IViewFor<TViewModel>
 87            where TViewModel : ReactiveObject, IValidatableViewModel
 88        {
 1689            if (viewModel is null)
 90            {
 091                throw new ArgumentNullException(nameof(viewModel));
 92            }
 93
 1694            if (viewModelProperty is null)
 95            {
 096                throw new ArgumentNullException(nameof(viewModelProperty));
 97            }
 98
 1699            if (viewProperty is null)
 100            {
 0101                throw new ArgumentNullException(nameof(viewProperty));
 102            }
 103
 16104            return ValidationBinding.ForProperty(view, viewModelProperty, viewProperty, formatter);
 105        }
 106
 107        /// <summary>
 108        /// Binds the overall validation of a ViewModel to a specified View property.
 109        /// </summary>
 110        /// <typeparam name="TView">IViewFor of TViewModel.</typeparam>
 111        /// <typeparam name="TViewModel">ViewModel type.</typeparam>
 112        /// <typeparam name="TViewProperty">View property type.</typeparam>
 113        /// <param name="view">IViewFor instance.</param>
 114        /// <param name="viewModel">ViewModel instance.</param>
 115        /// <param name="viewProperty">View property to bind the validation message.</param>
 116        /// <param name="formatter">Validation formatter. Defaults to <see cref="SingleLineFormatter"/>.</param>
 117        /// <returns>Returns a <see cref="IDisposable"/> object.</returns>
 118        [SuppressMessage("Design", "CA1801: Parameter unused", Justification = "Used for generic resolution")]
 119        public static IDisposable BindValidation<TView, TViewModel, TViewProperty>(
 120            this TView view,
 121            TViewModel viewModel,
 122            Expression<Func<TView, TViewProperty>> viewProperty,
 123            IValidationTextFormatter<string>? formatter = null)
 124            where TViewModel : ReactiveObject, IValidatableViewModel
 125            where TView : IViewFor<TViewModel>
 126        {
 4127            if (viewModel is null)
 128            {
 0129                throw new ArgumentNullException(nameof(viewModel));
 130            }
 131
 4132            if (viewProperty is null)
 133            {
 0134                throw new ArgumentNullException(nameof(viewProperty));
 135            }
 136
 4137            return ValidationBinding.ForViewModel<TView, TViewModel, TViewProperty>(view, viewProperty, formatter);
 138        }
 139
 140        /// <summary>
 141        /// Binds a <see cref="ValidationHelper" /> from a ViewModel to a specified View property.
 142        /// </summary>
 143        /// <typeparam name="TView">IViewFor of TViewModel.</typeparam>
 144        /// <typeparam name="TViewModel">ViewModel type.</typeparam>
 145        /// <typeparam name="TViewProperty">View property type.</typeparam>
 146        /// <param name="view">IViewFor instance.</param>
 147        /// <param name="viewModel">ViewModel instance.</param>
 148        /// <param name="viewModelHelperProperty">ViewModel's ValidationHelper property.</param>
 149        /// <param name="viewProperty">View property to bind the validation message.</param>
 150        /// <param name="formatter">Validation formatter. Defaults to <see cref="SingleLineFormatter"/>.</param>
 151        /// <returns>Returns a <see cref="IDisposable"/> object.</returns>
 152        [SuppressMessage("Design", "CA1801: Parameter unused", Justification = "Used for generic resolution")]
 153        public static IDisposable BindValidation<TView, TViewModel, TViewProperty>(
 154            this TView view,
 155            TViewModel viewModel,
 156            Expression<Func<TViewModel?, ValidationHelper>> viewModelHelperProperty,
 157            Expression<Func<TView, TViewProperty>> viewProperty,
 158            IValidationTextFormatter<string>? formatter = null)
 159            where TView : IViewFor<TViewModel>
 160            where TViewModel : ReactiveObject, IValidatableViewModel
 161        {
 6162            if (viewModel is null)
 163            {
 0164                throw new ArgumentNullException(nameof(viewModel));
 165            }
 166
 6167            if (viewModelHelperProperty is null)
 168            {
 0169                throw new ArgumentNullException(nameof(viewModelHelperProperty));
 170            }
 171
 6172            if (viewProperty is null)
 173            {
 0174                throw new ArgumentNullException(nameof(viewProperty));
 175            }
 176
 6177            return ValidationBinding.ForValidationHelperProperty(view, viewModelHelperProperty, viewProperty, formatter)
 178        }
 179
 180        /// <summary>
 181        /// Creates a binding to a View property.
 182        /// </summary>
 183        /// <typeparam name="TTarget">Observable of any type.</typeparam>
 184        /// <typeparam name="TValue">Any type.</typeparam>
 185        /// <param name="this">Current observable instance.</param>
 186        /// <param name="target">Target instance.</param>
 187        /// <param name="viewExpression">Expression to discover View properties.</param>
 188        /// <returns>Returns a <see cref="IDisposable"/> object.</returns>
 189        [Obsolete("This method is a part of ReactiveUI internals and will be " +
 190                  "removed from ReactiveUI.Validation public API soon.")]
 191        public static IDisposable BindToDirect<TTarget, TValue>(
 192            IObservable<TValue> @this,
 193            TTarget target,
 194            Expression viewExpression)
 195        {
 0196            if (@this is null)
 197            {
 0198                throw new ArgumentNullException(nameof(@this));
 199            }
 200
 0201            if (target is null)
 202            {
 0203                throw new ArgumentNullException(nameof(target));
 204            }
 205
 0206            if (viewExpression is null)
 207            {
 0208                throw new ArgumentNullException(nameof(viewExpression));
 209            }
 210
 0211            var setter = Reflection.GetValueSetterOrThrow(viewExpression.GetMemberInfo())!;
 0212            if (viewExpression.GetParent().NodeType == ExpressionType.Parameter)
 213            {
 0214                return @this.Subscribe(
 0215                    x => setter(target, x, viewExpression.GetArgumentsArray()),
 0216                    ex => LogHost.Default.Error(ex, $"{viewExpression} Binding received an Exception!"));
 217            }
 218
 0219            var bindInfo = @this.CombineLatest(
 0220                target.WhenAnyDynamic(viewExpression.GetParent(), x => x.Value),
 0221                (val, host) => new { val, host });
 222
 0223            return bindInfo
 0224                .Where(x => x.host != null)
 0225                .Subscribe(
 0226                    x => setter(x.host, x.val, viewExpression.GetArgumentsArray()),
 0227                    ex => LogHost.Default.Error(ex, $"{viewExpression} Binding received an Exception!"));
 228        }
 229    }
 230}