Как вызвать реактивную команду и дождаться побочного эффекта перед выполнением действия подписки - PullRequest
0 голосов
/ 26 марта 2020

Я использую ReactiveUI и сторонние разработчики для отображения изображений с возможностью отмены / повтора. У меня есть модель представления с командой для изменения выбранного изображения, и я хотел бы выполнить следующие действия, когда я нажимаю на кнопку отмены:

  1. Найти изображение, на котором произойдет следующее действие отмены
  2. Позвоните моей команде, чтобы изменить выбранное изображение
  3. Дождитесь появления наблюдаемой, реагирующей на выбранное изображение, чтобы перезагрузить аннотации на изображении
  4. Выполнить действие отмены изображения

У меня есть нечто, похожее на

ViewModels:

public class MyViewModel : ReactiveObject
{
  public MyViewModel()
  {
    SelectImage = ReactiveCommand.Create<ImageViewModel, ImageViewModel>(phase => /* some code */);
    _selectedImage = SelectImage.ToProperty(this, x => x.SelectedImage, someDefaultValue);
  }

  private readonly ObservableAsPropertyHelper<ImageViewModel> _selectedImage ;
  public ImageViewModelSelectedImage=> _selectedImage.Value;

  public ReactiveCommand<ImageViewModel, ImageViewModel> SelectImage { get; }
}

public class ImageViewModel
{
  private object? _annot1;
  public object? Annotation1
  {
    get => _annot1;
    set => this.RaiseAndSetIfChanged(ref _annot1, value);
  }

  private object? _annot2;
  public object? Annotation2
  {
    get => _annot2;
    set => this.RaiseAndSetIfChanged(ref _annot2, value);
  }
}

Просмотр ctor:

var onAnnotationsLoaded = ViewModel.WhenAnyValue(x => x.SelectedImage.Annotation1, x => x.SelectedImage.Annotation2, (x, y) => Unit.Default)
  .Skip(1)
  .Throttle(TimeSpan.FromMilliseconds(100))
  .Select(_ => Observable.Start(() => LoadAnnotations(), RxApp.MainThreadScheduler));

onAnnotationsLoaded
  .Subscribe(_ => { })
  .DisposeWith(disposables);

UndoButton.Events()
  .Click
  .Select(_ => FindImageToSelect())
  .Select(image => ViewModel.SelectImage.Execute(image))
  .Switch()
  .Select(_ => onAnnotationsLoaded);
  .Select(x => x) // breakpoint here is called
  .Switch()
  .Select(x => x) // breakpoint here is called only the 2nd time undo button is clicked
  .Subscribe(_ => /* do the undo action */);

Я пытался заменить Observable.Start с другими методами, но на самом деле ни один из них не работает так, как мне хотелось бы.

Я почти уверен, что где-то в моей трубке или в ментальной модели наблюдаемых объектов что-то совершенно не так, но я не могу выяснить, что .

...