ObservableChangeSet 等待列表准备好后再观看

ObservableChangeSet wait until list is ready before watching

我们有一个列表页面,我们可以在其中启用或禁用 [​​=29=]thing™ 使用 <switch /> That thing™ is使用 IsActive 标志切换

public class Thing
{
    /* ... */
    [Reactive] public bool IsActive { get; set; }
}

给定以下更改侦听器,想法是当 IsActive 属性 更改时(切换开关上的用户交互),我们调用 _saveItemCommand 来保存实体新 IsActiveState.

public ObservableCollection<Thing> DataObjectList {get;} = new ObservableCollection<Thing>();

public MyClass()
{
    _saveItemCommand  = ReactiveCommand.CreateFromTask(SaveItemInternal);
    _listWatcher = DataObjectList
        .ToObservableChangeSet()
        .AsObservableList()
        .Connect()
        .WhenPropertyChanged(x => x.IsActive)
        .Throttle(TimeSpan.FromMilliseconds(250))
        .ObserveOn(RxApp.MainThreadScheduler)
        .Select(x => x.Sender)
        .InvokeCommand(_saveItemCommand);
}

public void OnNavigatingTo()
{
    var newItems = _myService.GetNewItems();
    DataObjectList.AddRange(newItems);
}

public void OnDestroy()
{
    _listWatcher?.Dispose();
}

我遇到的问题是,当我设置列表时,似乎在调用 AddRange 后立即对列表中的最后一项调用该命令。

我试过使用 .Skip(1) 但没有任何运气,但有一件似乎有效但很丑的事情是 .Skip(DataObjectList.Length)

我怎样才能做到直到用户第一次切换开关时才调用命令?设置此侦听器的正确方法是什么?

您很可能想要添加一个 Where 语句来指示它应该只在 IsActivated 开关上调用。

    _listWatcher = DataObjectList
        .ToObservableChangeSet()
        .AsObservableList()
        .Connect()
        .WhenPropertyChanged(x => x.IsActive)
        .Throttle(TimeSpan.FromMilliseconds(250))
        .ToCollection()
        .Where(x => x.Any(value => value.IsActive))
        .ObserveOn(RxApp.MainThreadScheduler)
        .Select(x => x.Sender)
        .InvokeCommand(_saveItemCommand);

所以我添加的两行是

        .ToCollection()
        .Where(x => x.Any(value => value.IsActive))

ToCollection() 会将其转换为可观察列表,而 Where 会将您的可观察对象限制在 IsActive 值发生变化时。

如果您希望它只在 Where() 调用之后发生一次,您可能希望添加一个 FirstAsync() 调用。

在对 Glenn 的回答发表评论并与 Rodney 进行一些额外对话之后,这就是最终起作用的方法。

_listWatcher = DataObjectList
    .ToObservableChangeSet()
    .AsObservableList()
    .Connect()
    .WhenPropertyChanged(x => x.IsActive)
    .Throttle(TimeSpan.FromMilliseconds(250))
    .Skip(1)
    .DistinctUntilChanged()
    .ObserveOn(RxApp.MainThreadScheduler)
    .Select(x => x.Sender)
    .InvokeCommand(_createActivationsInternal);