无法使简单的 ReactiveUI 示例正常工作

Trouble to get simple ReactiveUI sample to work

我刚开始学习 ReactUI 并尝试遵循这个示例:https://www.codeproject.com/Articles/801986/Using-ReactiveUI-for-WinForms-MVVM-Design 我开始感到沮丧,因为我无法让它工作。这是问题的代码(从示例中复制):

//
// ViewModel example
//
namespace WinFormMVVM.ViewModels
{
    public class HomeViewModel : ReactiveUI.ReactiveObject
    {
        string ModelString;
        public string EnteredText
        {
            get { return ModelString; }
            set { this.RaiseAndSetIfChanged( ref ModelString, value);}
        }

        string statusString = "";
        public string Status
        {
            get{return statusString;}
            set{this.RaiseAndSetIfChanged(ref statusString,value);}
        }

        public ReactiveCommand<object> OKCmd { get; private set; }

        public HomeViewModel
        {
            var OKCmdObs = this.WhenAny(vm => vm.EnteredText, 
                s => !string.IsNullOrWhiteSpace(s.Value));
            OKCmd = ReactiveCommand.Create(OKCmdObs);           // <--- Trouble starts here
            OKCmd.Subscribe(_=> Status = EnteredText + " is saved.");
        }
    }
}

我标记了有问题的行。 编译此代码会导致此错误:

Error CS1503 Argument 1: cannot convert from 'System.IObservable<bool>' to 'System.Action'

我使用 ReactiveUI for WinForms Version 7.4.0(这似乎是最新的稳定版本)

github 上的 ReactiveUI 样本告诉我使用 ReactiveCommand.CreateAsyncTask(...),这是一个未知的方法。真的很郁闷...

谁能解释一下如何让示例工作。

所有 ReactiveCommand 工厂方法都接受 ActionFunc<T> 作为定义执行命令时要执行的操作的第一个参数。下一个参数是您正在寻找的设置 CanExecute 的参数。使您的代码工作更改

OKCmd = ReactiveCommand.Create(OKCmdObs);

OKCmd = ReactiveCommand.Create(() => { /* Do nothing */ }, OKCmdObs);

你或许也应该改变

public ReactiveCommand<object> OKCmd { get; private set; }

public ReactiveCommand<Unit, Unit> OKCmd { get; private set; }

Unit是一种类型,用来表示没有真正的价值,只是一个信号。

看起来本教程使用 RxUI v6.x,它的语法与 v7.x for ReactiveCommand 的语法略有不同。您可以在此处阅读 ReactiveCommandhttps://reactiveui.net/docs/handbook/commands/

我终于让示例开始工作了。作为其他人的参考,我必须做的更改:

//
// ViewModel example
//
namespace WinFormMVVM.ViewModels
{
    public class HomeViewModel : ReactiveUI.ReactiveObject
    {
        string ModelString;
        public string EnteredText
        {
            get { return ModelString; }
            set { this.RaiseAndSetIfChanged( ref ModelString, value);}
        }

        string statusString = "";
        public string Status
        {
            get{return statusString;}
            set{this.RaiseAndSetIfChanged(ref statusString,value);}
        }

        public ReactiveCommand<object> OKCmd { get; private set; }

        public HomeViewModel
        {
            var OKCmdObs = this.WhenAny(vm => vm.EnteredText, 
                                        s => !string.IsNullOrWhiteSpace(s.Value));

            // OKCmd = ReactiveCommand.Create(OKCmdObs);    
            // OKCmd.Subscribe(_=> Status = EnteredText + " is saved.");

            OKCmd = ReactiveCommand.CreateFromObservable(() => {
                Status = EnteredText + " is saved.";
                return Observable.Return(true);
            }, OKCmdObs);
        }
    }
}

好的,这似乎对我有用:

public class HomeViewModel : ReactiveObject
{
    private string ModelString;

    public string EnteredText
    {
        get { return ModelString; }
        set { this.RaiseAndSetIfChanged(ref ModelString, value); }
    }

    private string statusString = string.Empty;

    public string Status
    {
        get { return statusString; }
        set { this.RaiseAndSetIfChanged(ref statusString, value); }
    }

    public ReactiveCommand<System.Reactive.Unit, bool> OKCmd { get; private set; }

    public HomeViewModel()
    {
        var OkCmdObs = this.WhenAny(vm => vm.EnteredText,
            s => !string.IsNullOrWhiteSpace(s.Value));
        OKCmd = ReactiveCommand.CreateFromObservable(() =>
        {
            Status = EnteredText + " is saved.";
            return Observable.Return(true);
        }, OkCmdObs);
    }
}

注意,这是带有 ReactiveUI v10.1.5 的 VS2019