如何在Xamarin.Forms中使用ReactiveUI仅执行一次命令?



使用 RxUI for Xamarin.Forms,您将如何创建一个命令,该命令只自动执行一次(当页面最初出现时(,但该用户可以请求其稍后执行(例如从拉取到刷新类型的事件(?

我已经使用FromEventPattern将我的命令挂接到Appearing事件,但是当我导航回页面时,它会再次执行,这是一种不希望的行为。

这是我的方案:我需要在用户打开包含列表的页面时自动填充该列表。然后用户可以选择一个元素并在单独的页面中查看其详细信息(使用NavigationPage(,但是当用户返回列表页面时,它会被重新填充,这不应该发生。不过,用户应该能够通过按钮请求新数据或拉动以刷新。

谢谢。

使用 Dorus 提示:在您的页面构建器中,您需要从事件创建一个可观察量,然后Take第一个:

Observable.FromEventPattern(ev => Appearing += ev, ev => Appearing -= ev)
.Select(e => Unit.Default)
.Take(1)
.InvokeCommand(ViewModel.InitialCollectionLoad);

以下是我如何处理这种情况。您需要与此类似的行为,该行为仅在设置特定的已知值时调用您的命令。

// Only invoke the command when the property matches a known value that can't happen through normal execution
this.WhenAnyValue(vm => vm.SomeProperty)
.Where(sp => sp == null)
.Throttle(TimeSpan.FromSeconds(.25), TaskPoolScheduler.Default)
.Do(_ => Debug.WriteLine($"Refresh the List"))
.InvokeCommand(GetList)
.DisposeWith(SubscriptionDisposables);

在构造函数的末尾,设置 SomeProperty 以匹配已知值

this.SomeProperty = null; // or some value that makes sense

在这种情况下,您无需在 OnAppearing 中手动触发该命令 - 该命令在首次构造 ViewModel 时发生,并且在释放并重新创建 ViewModel 之前不会再次执行。 这对我来说似乎有点麻烦,所以我希望更聪明、更有经验的 RxUI 向导会插话,但它可以完成工作。

如果您希望保留 OnAppearing 调用,也可以通过设置 ReactiveCommand 的 canExecute 属性并对 PullToRefresh 操作使用完全不同的 ReactiveCommand 来处理此问题(即使这两个命令的行为相同(。在此方案中,您希望在最初填充列表后使 canExecute 始终为 false,因此即使用户返回到页面也不会触发初始填充。

var isInitialized = this.WhenAnyValue(vm => vm.IsInit).Select( _ => _ == false).DistinctUntilChanged();
InitList = ReactiveCommand.CreateFromTask( _ => 
{ 
// get list 
}, isInitialized);
RefreshList = ReactiveCommand.CreateFromTask( _ =>
{
// essentially the same as InitList, but with different/no canExecute parameters
});
InitList.ObserveOn(RxApp.MainThreadScheduler).Subscribe(result =>
{
this.IsInit = false
}).DisposeWith(SubscriptionDisposables);

这里的缺点是,显然,你有一些重复的逻辑

也许我误解了,但我经常这样做,所以我认为我不是。

我只是使用 VM 创建作为命令初始执行的触发器。然后,我将相同的命令与 XF 中的下拉刷新功能相关联。

所以我的虚拟机看起来像这样:

public class MyVM
{
public MYVM()
{
this.refreshCommand = ...;
this
.refreshCommand
.Execute()
.Subscribe()
_ => {},
_ => {});
}
public ReactiveCommand<...> RefreshCommand => this.refreshCommand;
}

这样,命令将在创建 VM 后立即执行,因此会尽快检索数据。但它不会再次重新执行,除非重新创建 VM 或用户拉取刷新。

相关内容

  • 没有找到相关文章

最新更新