ToProperty and BindTo - Get initial value without Subscribing

拟墨画扇 提交于 2019-12-11 02:41:11

问题


I'm using RXUI 6 with WPF in .NET 4.5.

I've been having trouble getting an initial value provided to my View when the ViewModel property it is bound to is backed by an ObservableAsPropertyHelper.

According to the documentation:

ToProperty / OAPH changes

  • ObservableAsPropertyHelper no longer is itself an IObservable, use WhenAny to observe it.

  • ObservableAsPropertyHelper now lazily Subscribes to the source only when the Value is read for the first time. This significantly
    improves performance and memory usage, but at the cost of some "Why
    doesn't my test work??" confusion. If you find that your ToProperty
    "isn't working", this may be why.

I looked at this question which seems to address my same problem, but the answer provided works in testing and with a ReactiveCommand. I cannot figure out the cleanest way to get this to work in my situation with any IObservable<> not necessarily a ReactiveCommand (oversimplified below).

Example ViewModel:

public class ViewModel : ReactiveObject
{
    private readonly ObservableAsPropertyHelper<string> _message;

    public ViewModel()
    {
       var someObservable = Observable.Return("Hello");

        _message = someObservable
            .ToProperty(this, t => t.Message);
    }

    public string Message
    {
        get
        {
            return _message.Value;
        }
    }
}

Example View Code-behind:

public partial class View : UserControl, IViewFor<ViewModel>
{
     public View()
     {
        InitializeComponent();

        this.WhenAnyValue(t => t.ViewModel.Message)
            .BindTo(this, t => t.MessageTextBlock.Text);
     }
     // ... IViewFor Stuff....
}

So right now, the Message TextBox will not contain the initial value. However if in my ViewModel I was to add the line to the contructor:

this.WhenAnyValue(t => t.Message).Subscribe(s => {});

It will now fire off to the TextBlock because now there is a subscription. So I'm guessing that the .BindTo() method never actually counts as a subscription? Or it is laziness on top of laziness? Does this empty subscription negate the performance benefits from it being lazy? Or should I not use .BindTo() and just use a .Subscribe() to assign the TextBlock?

**** EDIT **** Ok, there might be something else going on in my code as I have not been able to reproduce this behavior consistently. I will report back if I find the root cause.

* EDIT 2 * I have confirmed that I had another issue that was causing the misfiring, not OAPH. The .ToProperty and .BindTo seem to be working consistently as expected now. Thanks.


回答1:


It will now fire off to the TextBlock because now there is a subscription. So I'm guessing that the .BindTo() method never actually counts as a subscription?

BindTo immediately Subscribes to the source and should kick off the OAPH. However, this Subscription won't actually happen until the View gets a ViewModel:

// Can't subscribe to (null).Message!
this.WhenAnyValue(t => t.ViewModel.Message)


来源:https://stackoverflow.com/questions/25252210/toproperty-and-bindto-get-initial-value-without-subscribing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!