绑定到ReactiveCommand.IsExecuting

Rat*_*ica 7 reactiveui

我想知道绑定到ReactiveCommand的推荐方法IsExecuting.

问题是初始命令执行(在构造函数结束时启动)不是使用IsLoading绑定更新WPF控件,尽管后续调用按预期工作.

更新2添加测试绑定代码

这显示了装饰器内容时IsLoading为真

<ac:AdornedControl IsAdornerVisible="{Binding IsLoading}">
    <ac:AdornedControl.AdornerContent>
        <controls1:LoadingAdornerContent/>
    </ac:AdornedControl.AdornerContent>
    <fluent:ComboBox
        ItemsSource="{Binding Content, Mode=OneWay}"
        DisplayMemberPath="Name"
        SelectedValuePath="ContentId"
        SelectedValue="{Binding SelectedContentId}"
        IsSynchronizedWithCurrentItem="True"
    />
</ac:AdornedControl>
Run Code Online (Sandbox Code Playgroud)

更新

我发现了这个:https: //github.com/reactiveui/rxui-design-guidelines

并认为我应该能够做到这样的事情:

this._isLoading = this.WhenAnyValue(x => x.LoadCommand.IsExecuting)
    .ToProperty(this, x => x.IsLoading);
Run Code Online (Sandbox Code Playgroud)

但它给出了编译错误:

方法'ReactiveUI.OAPHCreationHelperMixin.ToProperty <TObj,TRet>的类型参数(System.IObservable <TRet>,TObj,System.Linq.Expressions.Expression <System.Func <TObj,TRet >>,TRet,System.Reactive. Concurrency.IScheduler)'无法从用法中推断出来.尝试显式指定类型参数.

我也尝试过:

this._isLoading = this.WhenAnyValue(x => x.LoadCommand.IsExecuting)
    .ToProperty<TheViewModel, bool>(this, x => x.IsLoading);
Run Code Online (Sandbox Code Playgroud)

但得到编译错误:

'System.IObservable <System.IObservable <bool >>'不包含'ToProperty'的定义和最佳扩展方法重载'ReactiveUI.OAPHCreationHelperMixin.ToProperty <TObj,TRet>(System.IObservable <TRet>,TObj,System .Linq.Expressions.Expression <System.Func <TObj,TRet >>,TRet,System.Reactive.Concurrency.IScheduler)'有一些无效的参数

实例参数:无法从'System.IObservable>'转换为'System.IObservable'

原来下面

我的帖子末尾列出的代码通过访问IsLoading属性来进行初始绑定,听起来就像启动订阅一样.但是从进一步的阅读来看,我似乎应该使用它WhenAny,我似乎无法弄清楚我的鼻子前面放了什么:

ToProperty和BindTo - 获取初始值而无需订阅

添加:

this.WhenAnyValue(x => x.LoadCommand.IsExecuting);
Run Code Online (Sandbox Code Playgroud)

也有效,但还有更好的方法吗?

我正在考虑删除ObservableAsPropertyHelper它,因为它似乎没有为我做太多,并使IsLoading正常的属性,如:

private bool _isLoading;

public bool IsLoading
{
    get { return _isLoading; }
    set { this.RaiseAndSetIfChanged(ref _isLoading, value); }
}
Run Code Online (Sandbox Code Playgroud)

并执行类似下面的操作,但它不会编译,因为它试图将IObservable< bool>一个bool 分配给:

this.WhenAnyValue(x => x.LoadCommand.IsExecuting)
   .Subscribe(x => IsLoading = x);
Run Code Online (Sandbox Code Playgroud)

当前代码:

private readonly ObservableAsPropertyHelper<bool> _isLoading;

public bool IsLoading
{
   get { return _isLoading.Value; }
}

LoadCommand = ReactiveCommand.CreateAsyncTask(async _ =>
{
    //go do command stuff like fetch data from a database
}

LoadCommand.IsExecuting.ToProperty(this, x => x.IsLoading, out _isLoading);

//works if I have this line
var startSubscription = IsLoading;

LoadCommand.ExecuteAsyncTask();
Run Code Online (Sandbox Code Playgroud)

Ana*_*tts 7

并认为我应该能够做到这样的事情:

你有正确的想法,但语法有点偏,尝试:

this.LoadCommand.IsExecuting
    .ToProperty(this, x => x.IsLoading, out _isLoading);
Run Code Online (Sandbox Code Playgroud)

如果你要对可以改变的对象(即你有一个长表达式)这样做,那么WhenAnyObservable你可以使用一种特殊的方法来代替WhenAnyValue:

this.WhenAnyObservable(x => x.SomeObjectThatMightBeReplaced.IsExecuting)
    .ToProperty(this, x => x.IsLoading, out _isLoading);
Run Code Online (Sandbox Code Playgroud)


Jon*_*ois 4

我以前遇到过这个问题,我想你所经历的就在这里

ToProperty / OAPH 变更

  • ObservableAsPropertyHelper 本身不再是 IObservable,使用 WhenAny 来观察它。

  • ObservableAsPropertyHelper 现在仅在第一次读取 Value 时延迟订阅源。这显着提高了性能和内存使用率,但代价是“为什么我的测试不起作用?” 困惑。如果您发现您的 ToProperty“不起作用”,这可能就是原因。

它是惰性的,因此您必须订阅它(即,如果使用 OAPH,则从属性请求一个值)才能使其工作。这就是为什么您注意到您var startSubscription = IsLoading;“解决”了问题。

知道这一点让我更容易确定这是否是一个问题,或者只是在单元测试期间需要记住的事情,知道在我的应用程序中这些属性将被绑定并因此被订阅,使其毫无意义实践。你知道,整个“树倒在森林里,没有人听到”的想法。

我认为你应该坚持ToProperty现有的,恕我直言,这似乎是正确的方法。