简体   繁体   中英

How do I combine these two commands into one?

In the body of my class, I have this line of code:

private ReactiveCommand<object> _displayCommand = ReactiveCommand.Create();

In the class constructor, I set up a subscription:

_displayCommand.Subscribe(_ =>
{
    MessageBox.Show("Button clicked.");
});

Is it possible to write some sort of extension method to effectively combine these two commands into one, so with a single function call we can call both ReactiveCommand.Create(), and create a subscription using Reactive Extensions (RX)?

This would group all logically related code together, and make the ViewModel much cleaner.

Update

This is what I have so far (thanks to @jt000):

public static ReactiveCommand<object> CreateAndSubscribe(Func<object> fn)
{
    var displayCommand = ReactiveCommand.Create();
    displayCommand.Subscribe<object>(_ => fn.Invoke());
    return displayCommand;
}

private ReactiveCommand<object> _displayCommand = CreateAndSubscribe(() =>
{
    return MessageBox.Show("Hello");
});

public ReactiveCommand<object> DisplayCommand
{
    get { return _displayCommand; }
    protected set { _displayCommand = value; }
}

However, I need to occasionally insert the call .Buffer(TimeSpan.FromSeconds(1). between displayCommand and .Subscribe(fn) , and this function is not generic enough to do that. What I really need is some way of passing the entire subscription in to CreateAndSubscribe - perhaps some Func that takes an IObservable ?

This means I could use something like the following function call:

private ReactiveCommand<object> _displayCommand = 
    CreateAndSubscribe(o => o.Subscribe(() =>
                              {
                                  return MessageBox.Show("Hello");
                              }));

and if I wanted to insert .Buffer(TimeSpan.FromSeconds(1)) :

private ReactiveCommand<object> _displayCommand = 
    CreateAndSubscribe(o => o.Buffer(TimeSpan.FromSeconds(1)).Subscribe(() =>
                              {
                                  return MessageBox.Show("Hello");
                              }));

This API is actually intentionally missing, because there is no elegant way for Create to return both the ReactiveCommand and the IDisposable result from Create . You could do something ugly with out parameters, but it'd end up being pretty cumbersome.

While I definitely also sometimes miss a CreateWithAction or something like it, immediate Subscribe s are kind of defeating the composability aspect of RxUI; this API makes it harder to put stuff together, not easier.

Would this work?

public static ReactiveCommand<object> CreateAndSubscribe(Func<object> fn) 
{
    var displayCommand = ReactiveCommand.Create();
    displayCommand.Subscribe(fn);
    return displayCommand;
}

Usage:

CreateAndSubscribe(_ => MessageBox.Show("hi"));

Yes, but there's not much point because instance members aren't in scope when defining a field. The handlers you pass to Subscribe can't reference any of the view model's fields or call any of its methods. You wouldn't be able to do much more than what you've shown in your example, such as call MessageBox.Show or something like that.

Put something like this in a static class.

   public static void CreateAndSubscribe(this displayCommand)
    {
        displayCommand = ReactiveCommand.Create();
        displayCommand.Subscribe(_ =>
        {
            MessageBox.Show("Button clicked.");
        });
    }

Access it like any other extension method:

_displayCommand.CreateAndSubscribe();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM