/// <summary> /// Observe collection element's IObservable sequence. /// </summary> /// <typeparam name="TCollection">Type of collection</typeparam> /// <typeparam name="TElement">Type of collection element</typeparam> /// <typeparam name="TProperty">Type of observable property element</typeparam> /// <param name="source">Source collection</param> /// <param name="propertySelector">IObservable selection expression</param> /// <returns>IObservable sequence</returns> internal static IObservable <PropertyPack <TElement, TProperty> > ObserveElementObservableProperty <TCollection, TElement, TProperty>(this TCollection source, Expression <Func <TElement, IObservable <TProperty> > > propertySelector) where TCollection : INotifyCollectionChanged, IEnumerable <TElement> where TElement : class { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (propertySelector == null) { throw new ArgumentNullException(nameof(propertySelector)); } var memberExpression = (MemberExpression)propertySelector.Body; var propertyInfo = memberExpression.Member as PropertyInfo; if (propertyInfo == null) { throw new ArgumentException($"{nameof(propertySelector)} is not property expression"); } var propertyName = default(string); // no use var getter = AccessorCache <TElement> .LookupGet(propertySelector, out propertyName); return(This.ObserveElementCore <TCollection, TElement, PropertyPack <TElement, TProperty> > ( source, (x, observer) => getter(x).Subscribe(y => { var pair = PropertyPack.Create(x, propertyInfo, y); observer.OnNext(pair); }) )); }
/// <summary> /// Converts target property's ErrorsChanged 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> /// <returns></returns> public static IObservable <TProperty> ObserveErrorInfo <TSubject, TProperty>( this TSubject subject, Expression <Func <TSubject, TProperty> > propertySelector) where TSubject : INotifyDataErrorInfo { var accessor = AccessorCache <TSubject> .LookupGet(propertySelector, out var propertyName); var result = subject.ErrorsChangedAsObservable() .Where(e => e.PropertyName == propertyName) .Select(_ => accessor.Invoke(subject)); return(result); }
private static IObservable <TProperty> ObserveSimpleProperty <TSubject, TProperty>( this TSubject subject, Expression <Func <TSubject, TProperty> > propertySelector, bool isPushCurrentValueAtFirst = true) where TSubject : INotifyPropertyChanged { var isFirst = true; var accessor = AccessorCache <TSubject> .LookupGet(propertySelector, out var propertyName); return(Observable.Defer(() => { var flag = isFirst; isFirst = false; var q = subject.PropertyChangedAsObservable() .Where(e => e.PropertyName == propertyName || string.IsNullOrEmpty(e.PropertyName)) .Select(_ => accessor.Invoke(subject)); return (isPushCurrentValueAtFirst && flag) ? q.StartWith(accessor.Invoke(subject)) : q; })); }
/// <summary> /// Converts NotificationObject's property changed to an observable sequence. /// </summary> /// <param name="propertySelector">Argument is self, Return is target property.</param> /// <param name="isPushCurrentValueAtFirst">Push current value on first subscribe.</param> public static IObservable <TProperty> ObserveProperty <TSubject, TProperty>( this TSubject subject, Expression <Func <TSubject, TProperty> > propertySelector, bool isPushCurrentValueAtFirst = true) where TSubject : INotifyPropertyChanged { string propertyName; var accessor = AccessorCache <TSubject> .LookupGet(propertySelector, out propertyName); var isFirst = true; var result = Observable.Defer(() => { var flag = isFirst; isFirst = false; var q = subject.PropertyChangedAsObservable() .Where(e => e.PropertyName == propertyName) .Select(_ => accessor.Invoke(subject)); return((isPushCurrentValueAtFirst && flag) ? q.StartWith(accessor.Invoke(subject)) : q); }); return(result); }