【问题标题】:ObservableChangeSet wait until list is ready before watchingObservableChangeSet 等到列表准备好再观看
【发布时间】:2020-02-21 01:26:30
【问题描述】:

我们有一个列表页面,我们可以在其中使用 <switch /> 启用或禁用 thing™,该 thing™ 使用 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)

如何才能使命令在用户第一次切换开关时才被调用?设置此侦听器的正确方法是什么?

【问题讨论】:

    标签: dynamic-data reactiveui


    【解决方案1】:

    您很可能希望添加 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() 会将其转换为 observable 列表,Where 会将您的 observable 限制在 IsActive 值发生变化时。

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

    【讨论】:

    • 我在原始帖子中的代码在 IsActive 切换时调用 save 方法确实表现正确(它可以是真或假)。问题是它在视图模型的设置过程中调用 save 方法,而不是仅在用户与视图交互时调用。
    • Where 子句之后添加Skip(1)。这是跳过第一个。你也可以StartWith(false).DistinctUntilChanged()
    • @RodneyLittles IsActive 可以是真或假(来自数据库),并且真或假应该触发命令。如果我没看错的话,Where 子句正在等待值为true,这不起作用。
    • 我对原始问题进行了一些编辑以增加清晰度
    • @ChaseFlorell 这很有意义,因为您正在跳过第一组更改。那是我对StartWith(false).DistinctUntilChanged() 的想法,但取决于不起作用的值。正在发生的事情是您正在使用WhenAnyPropertyChanged 为列表中的所有项目发出更改通知。我知道有一种方法可以使用 DD 来抑制更改通知,但不知道如何从 ObservableCollection 执行此操作。您可以尝试DeferUntilLoaded(),这应该可以解决初始加载问题。
    【解决方案2】:

    在格伦的回答和与罗德尼的一些额外对话之后,这就是最终奏效的方法。

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

    【讨论】:

      猜你喜欢
      • 2016-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-13
      • 1970-01-01
      • 1970-01-01
      • 2018-12-03
      • 1970-01-01
      相关资源
      最近更新 更多