0

I'm trying to avoid an update to a property if another property is changing. So I've come up with the following (in my ViewModel):

this.WhenAnyObservable(
    x => x.WhenAnyValue( y => y.Asset.CurrentValuation ),
    x => x.Changing,
    (currentValuation, changing) => changing.PropertyName != "CurrentValuationCalculated"
)

However, ReactiveUI throws the following error inside ExpressionRewriter.VisitMethodCall:

throw new NotSupportedException("Index expressions are only supported with constants.")

If I remove the WhenAnyValue line, it works. So I'm assuming it's something to do with the expression inside WhenAnyValue?

Without delving into what the ExpressionRewriter code actually does, what is it complaining about? Have I made some sort of simple error?

Update

So I've entered this instead:

this.WhenAnyObservable(
    x => x.Asset.CurrentValuation,
    x => x.Changing,
    ( currentValuation, changing ) => changing.PropertyName != "CurrentValuationCalculated"
)

However, the compiler complains about x.Asset.CurrentValuation and says:

Cannot implicitly convert type 'decimal?' to 'System.IObservable<ReactiveUI.IReactivePropertyChangedEventArgs<ReactiveUI.IReactiveObject>>'
Mitkins
  • 4,031
  • 3
  • 40
  • 77

1 Answers1

0

Short answer is yes.

The longer answer is WhenAnyObservable will provide you the change notification, so you don't really need the WhenAnyValue. You would generally use WhenAnyValue on a ViewModel property to force a subscription to the change notification. The observable sequence is inherently providing change notification via OnNext

Edit

Notice below I am observing an IObservable in the WhenAnyObservable and a view model property in WhenAnyValue. You don't need to unwrap the value in the call to WhenAnyObservable to get the value out.

public class MainViewModel : ReactiveObject
{
    private string _property;

    public IObservable<bool> MyObservabe { get; }

    public string MyProperty { get => _property; set => this.RaiseAndSetIfChanged(ref _property, value); }

    public MainViewModel()
    {
        MyObservabe = Observable.Interval(TimeSpan.FromSeconds(1)).Select(x => x > 5);

        this.WhenAnyObservable(x => x.MyObservabe);

        this.WhenAnyValue(x => x.MyProperty);
    }
}
Rodney Littles
  • 544
  • 2
  • 11
  • Can you provide an example to illustrate your answer? – Mitkins Dec 18 '18 at 23:01
  • Try making the WhenAnyValue portion its own member property and then use that property, instead. this.WhenAnyObservable(x => x.CurrentValuation, x => x.Changing) – Colt Bauman Dec 18 '18 at 23:23
  • I thought that `x.CurrentValuation` was a property - and not an Observable and that's why you had to use `WhenAnyValue`, to turn a property into an Observable. As seen in this response - https://stackoverflow.com/a/21342186/23401 – Mitkins Dec 18 '18 at 23:47
  • But what if I want to get up-to-date values of each at the same time? Originally, I just had `this.WhenAnyValue( x => x.Asset.CurrentValuation )`. But then I wanted to avoid the `Subscribe` if `CurrentValuationCalculated` is in the process of changing - which is only accessible via the `Changing` property/observable – Mitkins Dec 19 '18 at 00:20
  • Though I think my original logic is flawed. Setting `CurrentValuationCalculated` to true will auto-calculate `CurrentValuation` - but only **after** `CurrentValuationCalculated` has been changed! Still, I'm under the impression that the original statement should be possible - hence the question – Mitkins Dec 19 '18 at 00:32
  • The answer to your question is yes you can do what you want. `WhenAnyValue` will emit an observable sequence. I think your problem with your update is that you are looking a `x.Changing` which I believe is `this` changing which should be the View Model. You might want to do `x.Property.Changing` to look at the property that is changing. – Rodney Littles Dec 19 '18 at 01:56