Exemplo n.º 1
0
        /// <summary>
        /// <para>Converts NotificationObject's property to ReactiveProperty. Value is two-way synchronized.</para>
        /// <para>PropertyChanged raise on selected scheduler.</para>
        /// </summary>
        /// <typeparam name="TSubject">The type of the subject.</typeparam>
        /// <typeparam name="TProperty">The type of the property.</typeparam>
        /// <typeparam name="TResult">The type of the result.</typeparam>
        /// <param name="subject">The subject.</param>
        /// <param name="propertySelector">Argument is self, Return is target property.</param>
        /// <param name="convert">Convert selector to ReactiveProperty.</param>
        /// <param name="convertBack">Convert selector to source.</param>
        /// <param name="mode">ReactiveProperty mode.</param>
        /// <returns></returns>
        public static ReactivePropertySlim <TResult> ToReactivePropertySlimAsSynchronized <TSubject, TProperty, TResult>(
            this TSubject subject,
            Expression <Func <TSubject, TProperty> > propertySelector,
            Func <IObservable <TProperty>, IObservable <TResult> > convert,
            Func <IObservable <TResult>, IObservable <TProperty> > convertBack,
            ReactivePropertyMode mode = ReactivePropertyMode.DistinctUntilChanged | ReactivePropertyMode.RaiseLatestValueOnSubscribe)
            where TSubject : INotifyPropertyChanged
        {
            if (ExpressionTreeUtils.IsNestedPropertyPath(propertySelector))
            {
                var         result     = new ReactivePropertySlim <TResult>(mode: mode);
                var         observer   = PropertyObservable.CreateFromPropertySelector(subject, propertySelector);
                IDisposable disposable = null;
                disposable = convert(subject.ObserveProperty(propertySelector, isPushCurrentValueAtFirst: true))
                             .Subscribe(x => result.Value = x);
                convertBack(result)
                .Subscribe(x => observer.SetPropertyPathValue(x), _ => disposable.Dispose(), () => disposable.Dispose());
                return(result);
            }
            else
            {
                var setter = AccessorCache <TSubject> .LookupSet(propertySelector, out _);

                var         result     = new ReactivePropertySlim <TResult>(mode: mode);
                IDisposable disposable = null;
                disposable = convert(subject.ObserveProperty(propertySelector, isPushCurrentValueAtFirst: true))
                             .Subscribe(x => result.Value = x);
                convertBack(result)
                .Subscribe(x => setter(subject, x), _ => disposable.Dispose(), () => disposable.Dispose());
                return(result);
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// <para>Converts NotificationObject's property to ReactiveProperty. Value is two-way synchronized.</para>
        /// <para>PropertyChanged raise on selected scheduler.</para>
        /// </summary>
        /// <typeparam name="TSubject">The type of the subject.</typeparam>
        /// <typeparam name="TProperty">The type of the property.</typeparam>
        /// <typeparam name="TResult">The type of the result.</typeparam>
        /// <param name="subject">The subject.</param>
        /// <param name="propertySelector">Argument is self, Return is target property.</param>
        /// <param name="convert">Convert selector to ReactiveProperty.</param>
        /// <param name="convertBack">Convert selector to source.</param>
        /// <param name="raiseEventScheduler">The raise event scheduler.</param>
        /// <param name="mode">ReactiveProperty mode.</param>
        /// <param name="ignoreValidationErrorValue">Ignore validation error value.</param>
        /// <returns></returns>
        public static ReactiveProperty <TResult> ToReactivePropertyAsSynchronized <TSubject, TProperty, TResult>(
            this TSubject subject,
            Expression <Func <TSubject, TProperty> > propertySelector,
            Func <IObservable <TProperty>, IObservable <TResult> > convert,
            Func <IObservable <TResult>, IObservable <TProperty> > convertBack,
            IScheduler raiseEventScheduler,
            ReactivePropertyMode mode       = ReactivePropertyMode.DistinctUntilChanged | ReactivePropertyMode.RaiseLatestValueOnSubscribe,
            bool ignoreValidationErrorValue = false)
            where TSubject : INotifyPropertyChanged
        {
            if (ExpressionTreeUtils.IsNestedPropertyPath(propertySelector))
            {
                var observer = PropertyObservable.CreateFromPropertySelector(subject, propertySelector);
                var result   = convert(Observable.Using(() => observer, x => x)
                                       .StartWith(observer.GetPropertyPathValue()))
                               .ToReactiveProperty(raiseEventScheduler, mode: mode);
                convertBack(result.Where(_ => !ignoreValidationErrorValue || !result.HasErrors))
                .Subscribe(x => observer.SetPropertyPathValue(x));
                return(result);
            }
            else
            {
                var setter = AccessorCache <TSubject> .LookupSet(propertySelector, out _);

                var result = convert(subject.ObserveProperty(propertySelector, isPushCurrentValueAtFirst: true))
                             .ToReactiveProperty(raiseEventScheduler, mode: mode);
                convertBack(result.Where(_ => !ignoreValidationErrorValue || !result.HasErrors))
                .Subscribe(x => setter(subject, x));
                return(result);
            }
        }
Exemplo n.º 3
0
 /// <summary>
 /// Converts NotificationObject's property changed to an observable sequence.
 /// </summary>
 /// <typeparam name="TSubject">The type of the subject.</typeparam>
 /// <typeparam name="TProperty">The type of the property.</typeparam>
 /// <param name="subject">The subject.</param>
 /// <param name="propertySelector">Argument is self, Return is target property.</param>
 /// <param name="isPushCurrentValueAtFirst">Push current value on first subscribe.</param>
 /// <returns></returns>
 public static IObservable <TProperty> ObserveProperty <TSubject, TProperty>(
     this TSubject subject, Expression <Func <TSubject, TProperty> > propertySelector,
     bool isPushCurrentValueAtFirst = true)
     where TSubject : INotifyPropertyChanged
 {
     return(ExpressionTreeUtils.IsNestedPropertyPath(propertySelector) ?
            ObserveNestedProperty(subject, propertySelector, isPushCurrentValueAtFirst) :
            ObserveSimpleProperty(subject, propertySelector, isPushCurrentValueAtFirst));
 }