이것은 내가 전에 wbe에 대한 해결책을 알았 기 때문에 이것은 내 부분에서 인터넷 검색이 잘 안되는 경우 여야합니다. 메소드 INotifyPropertyChanged.PropertyChanged
이벤트를 IObservable<Tuple<TProperty,TProperty>>
으로 변환 할 수있는 메소드입니다. 여기서 터플의 값은 속성의 oldValue 및 newValue를 나타 냅니까?Rx INotifyPropertyChanged to IObservable <Tuple <TProperty, TProperty >>
public static IObservable<Tuple<TProperty,TProperty>> ObservePropertyChanged<TNotifier, TProperty>(this TNotifier notifier,
Expression<Func<TNotifier, TProperty>> propertyAccessor,
bool startWithCurrent = false)
where TNotifier : INotifyPropertyChanged {
// Parse the expression to find the correct property name.
MemberExpression member = (MemberExpression)propertyAccessor.Body;
string name = member.Member.Name;
// Compile the expression so we can run it to read the property value.
var reader = propertyAccessor.Compile();
var propertyChanged = Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>(
handler => (sender, args) => handler(sender, args),
x => notifier.PropertyChanged += x,
x => notifier.PropertyChanged -= x);
// Filter the events to the correct property name, then select the value of the property from the notifier.
var newValues = from p in propertyChanged
where p.EventArgs.PropertyName == name
select reader(notifier);
throw new NotImplementedException();
}
:이 서명에 맞게 (credit for below to)
public static IObservable<TProperty> ObservePropertyChanged<TNotifier, TProperty>(this TNotifier notifier,
Expression<Func<TNotifier, TProperty>> propertyAccessor,
bool startWithCurrent = false)
where TNotifier : INotifyPropertyChanged {
// Parse the expression to find the correct property name.
MemberExpression member = (MemberExpression)propertyAccessor.Body;
string name = member.Member.Name;
// Compile the expression so we can run it to read the property value.
var reader = propertyAccessor.Compile();
var propertyChanged = Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>(
handler => (sender, args) => handler(sender, args),
x => notifier.PropertyChanged += x,
x => notifier.PropertyChanged -= x);
// Filter the events to the correct property name, then select the value of the property from the notifier.
var newValues = from p in propertyChanged
where p.EventArgs.PropertyName == name
select reader(notifier);
// If the caller wants the current value as well as future ones, use Defer() so that the current value is read when the subscription
// is added, rather than right now. Otherwise just return the above observable.
return startWithCurrent ? Observable.Defer(() => Observable.Return(reader(notifier)).Concat(newValues)) : newValues;
}
그리고 변환 :
그래서 나는 이런 식으로 뭔가를 취할 수있는 최선의 방법이 무엇인지 알고 싶어 편집 : 나는 많은 다른 연산자를 시도한 후 작동하는 것 뭔가를 알아 냈어. 이것이 올바른 방법일까요? 제가 빠진 것이 있습니까? 편집
public static IObservable<Tuple<TProperty,TProperty>> ObserveValueChanged<TNotifier, TProperty>(this TNotifier notifier,
Expression<Func<TNotifier, TProperty>> propertyAccessor,
bool startWithCurrent = false)
where TNotifier : INotifyPropertyChanged {
var observable = ObservePropertyChanged(notifier, propertyAccessor, startWithCurrent);
return observable.Scan(new Tuple<TProperty, TProperty>(default(TProperty), default(TProperty)),
(acc, p) => new Tuple<TProperty, TProperty>(acc.Item2, p));
}
:
public static IObservable<Tuple<TProperty, TProperty>> ObserveValueChanged2<TNotifier, TProperty>(this TNotifier notifier,
Expression<Func<TNotifier, TProperty>> propertyAccessor,
bool startWithCurrent = false)
where TNotifier : INotifyPropertyChanged {
// Compile the expression so we can run it to read the property value.
var reader = propertyAccessor.Compile();
var newValues = ObservePropertyChanged(notifier, propertyAccessor, false);
if (startWithCurrent) {
var capturedNewValues = newValues; //To prevent warning about modified closure
newValues = Observable.Defer(() => Observable.Return(reader(notifier))
.Concat(capturedNewValues));
}
return Observable.Create<Tuple<TProperty, TProperty>>(obs => {
Tuple<TProperty, TProperty> oldNew = null;
return newValues.Subscribe(v => {
if (oldNew == null) {
oldNew = Tuple.Create(default(TProperty), v);
} else {
oldNew = Tuple.Create(oldNew.Item2, v);
obs.OnNext(oldNew);
}
},
obs.OnError,
obs.OnCompleted);
});
}
추신 : 나는 다음과 같이 결국 기드온의 솔루션을 통합 필자는 현재 현재의 해결책을 찾았지만 결국 대답을 추가하거나 질문을 닫으면 어떤 에티켓을 위반하고 싶지 않습니다. (나중에 유용 할 수도 있으므로 삭제하지 않기를 바랍니다.) 여전히 이것이 최선의 방법이라고 확신하지 못합니다..
INotifyPropertyChanged는 이전 값에 대한 액세스를 제공하지 않는다. 이 이벤트는 당신이하려고하는 것에 적합하지 않다고 생각합니다. – cadrell0
ReplaySubject를 사용하여 값을 캡처하는 방법에 대한 토론이있었습니다. 그래서 나는 어떻게 든 초기 값을 포착 할 수 있다고 생각하고 항상 오래된 값과 현재/새로운 값의 엇갈린 창을 보여줍니다. 말이 돼? 나는 Rx에서 그것을하는 방법을 모른다. – Damian
나는 커스텀 이벤트를 생성하고 삶을 편하게 만들 것이다. – cadrell0