绑定到ReactiveCommand.IsExecuting

时间:2014-08-31 08:43:48

标签: 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>

更新

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

并且认为我应该可以做类似的事情:

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

但它给出了编译错误:

  

方法的类型参数   “ReactiveUI.OAPHCreationHelperMixin.ToProperty&LT;   TObj,TRet&gt;(System.IObservable&lt; TRet&gt;,TObj,   System.Linq.Expressions.Expression&LT; System.Func&LT; TObj,TRet&gt;&gt;,TRet,   System.Reactive.Concurrency.IScheduler)'无法从中推断出来   用法。尝试明确指定类型参数。

我也尝试过:

this._isLoading = this.WhenAnyValue(x => x.LoadCommand.IsExecuting)
    .ToProperty<TheViewModel, bool>(this, x => x.IsLoading);

但是得到了编译错误:

  

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

  

实例参数:无法转换   'System.IObservable&GT;'至   'System.IObservable'

原文

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

ToProperty and BindTo - Get initial value without Subscribing

添加:

this.WhenAnyValue(x => x.LoadCommand.IsExecuting);

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

我在考虑删除ObservableAsPropertyHelper,因为它似乎对我没有太大作用,并使IsLoading成为普通属性,如:

private bool _isLoading;

public bool IsLoading
{
    get { return _isLoading; }
    set { this.RaiseAndSetIfChanged(ref _isLoading, value); }
}

执行类似下面的操作,但它没有编译,因为它试图将IObservable< bool>分配给bool:

this.WhenAnyValue(x => x.LoadCommand.IsExecuting)
   .Subscribe(x => IsLoading = x);

当前代码:

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();

2 个答案:

答案 0 :(得分:7)

  

并且认为我应该可以做类似的事情:

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

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

如果您使用可以更改的对象(即您已经有一个长表达式)来执行此操作,那么您使用的是WhenAnyObservable而不是WhenAnyValue的特殊方法:

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

答案 1 :(得分:3)

我之前遇到过这种情况,我认为你遇到的是谎言here

  

ToProperty / OAPH更改

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

  •   
  • ObservableAsPropertyHelper现在懒惰只有在第一次读取Value时才订阅源。这显着提高了性能和内存使用率,但代价是“为什么我的测试工作没有?”#34;混乱。如果您发现您的ToProperty&#34;没有工作&#34;,这可能是原因。

  •   

它是懒惰的,所以你必须订阅它(即如果使用OAPH请求属性中的值)才能工作。这就是为什么你注意到你的var startSubscription = IsLoading;修复了&#39;这个问题。

知道这让我更容易确定这是否是一个问题,或者只是在我的单元测试中要记住的事情,知道在我的应用程序中这些属性将被绑定并因此订阅,制作在实践中没有实际意义。你知道,整棵树落在森林里,没有人在那里听到它&#34;想法。

我认为你应该坚持使用ToProperty,这似乎是恕我直言的方式。