在另一个视图模型中观察命令



我不确定如何为这个问题命名,因为我不确定出了什么问题,但是我在观察另一个视图模型中的命令时遇到了麻烦。

我有一个BoxPageViewModel,其中包含一个SourceCache<BoxViewModel>"框"和一个SourceCache<ItemViewModel>"项目"。 我希望能够将 ItemViewModel 添加到 BoxViewModel,然后应该将其从"Items"中删除。

我的计划是在BoxViewModel中使用一个Add命令,该命令将项目添加到BoxViewModel中的SourceList中。BoxPageViewModel 在其任何框调用"添加"时"侦听",然后从"项目"中删除该框的最新项

我查看了消息总线的文档,以了解如何观察何时调用另一个视图模型中的命令。我已经让它工作了,但不完全是。

我的问题是,从 ItemsSource 中删除项目的代码仅在首次设置 BoxViewModel 中的 ObservableAsPropertyHelper 'IsFull' 之前调用,我不知道为什么。 截至目前,如果盒子包含 2 个或更多项目,则"IsFull"应该是真的。当我将第一个项目添加到框中时,它从BoxPageViewModel中的项目中删除。但是当我添加第二项时,永远不会调用用于从项中删除该项的代码。

如果我删除"IsFull",它可以正常工作,但我真的需要一种方法来以某种方式判断所有盒子何时"满"或"完成"。

我尝试使用.ToObservableChangeSet().AutoRefreshOnObservable(x => x.Add)而不是.ToObservableChangeSet().AutoRefresh()但这没有区别。我在这里有点茫然,因为我不太确定这是如何工作的。我真的很想解释为什么代码会像现在这样。

奖励问题:我似乎也无法将BoxPageViewModel的"完成"属性变为true,即使我已经检查了_boxes.Select(b => b.All(x => x.IsFull))为真的测试方法。我定义此属性的方式有问题吗?

public class BoxViewModel : ReactiveObject
{
readonly ObservableAsPropertyHelper<bool> isFull;
public bool IsFull => isFull.Value;
public SourceList<Item> Items = new SourceList<Item>();
public ReactiveCommand<int, Unit> Add { get; }
public BoxViewModel()
{
Add = ReactiveCommand.Create<int>(AddToBox);
Items.Connect()
.ToCollection()
.Select(c => c.Count >= 2)
.ToProperty(this, x => x.IsFull, out isFull);
}
private void AddToBox(int id)
{
// Adding a new item while testing.
Items.Add(new Item { Id = id });
}
}

在BoxPageViewModel中,我尝试观察何时调用AddToBox命令,然后从其Items SourceCache中删除该项。

public class BoxPageViewModel : ReactiveObject, IRoutableViewModel
{
private SourceCache<Item, int> ItemsSource = new SourceCache<Item, int>(x => x.Id);
private SourceCache<BoxViewModel, int> BoxSource = new SourceCache<BoxViewModel, int>(x => x.Id);
private ReadOnlyObservableCollection<BoxViewModel> _boxes;
public ReadOnlyObservableCollection<BoxViewModel> Boxes => _boxes;
private ReadOnlyObservableCollection<Item> _items;
public ReadOnlyObservableCollection<Item> Items => _items;
readonly ObservableAsPropertyHelper<bool> done;
public bool Done => done.Value;
public BoxPageViewModel()
{
var box1 = new BoxViewModel { Id = 1 };
var box2 = new BoxViewModel { Id = 2 };
BoxSource.AddOrUpdate(box1);
BoxSource.AddOrUpdate(box2);
// I have left out the part where my items are created
ItemsSource.AddOrUpdate(items);
ItemsSource.Connect()
.ObserveOn(RxApp.MainThreadScheduler)
.Bind(out _items)
.Subscribe();
BoxSource.Connect()
.ObserveOn(RxApp.MainThreadScheduler)
.Bind(out _boxes)
.Subscribe();
_boxes.ToObservableChangeSet()
.ToCollection()
.Select(b => b.All(x => x.IsFull))
.ToProperty(this, x => x.Done, out done);
_boxes
.ToObservableChangeSet()
.AutoRefresh()
.Select(_ => WhenAnyBoxAdded())
.Switch()   
.Subscribe(box =>
{
var latestItem = box.Items.Items.Last();
ItemsSource.Remove(latestItem.Id);
});
}
IObservable<BoxViewModel> WhenAnyBoxAdded()
{
return _boxes
.Select(x => x.Add.Select(_ => x))
.Merge();
}
}

如果您选择使用消息中心。 类实现发布-订阅模式,允许在组件之间进行基于消息的通信,这些组件不方便按对象和类型引用进行链接。此机制允许发布者和订阅者在不相互引用的情况下进行通信,从而有助于减少它们之间的依赖关系。

首先,签名(此代码必须在之前执行(:

Xamarin.Forms.MessagingCenter.Subscribe<object>(this, "key", async message =>
{                
//your code here.
});

并发送消息:

Xamarin.Forms.MessagingCenter.Send<object>(new object(), "key");

最新更新