Search code examples
reactivereactiveui

Reset ReactiveUI ObservableAsPropertyHelper Value


I am building a simple DateTime calculator using a ReactiveUI ReactiveObject viewmodel.

It has a calculate command that calculates a value and correctly updates the result backed by an ObservableAsPropertyHelper<DateTime?> field.

I also have a ReactiveUICommand that is supposed to reset all of the UI values.

The problem that I am running into is how to reset the readonly "Result" value.

public class VM : ReactiveObject
{
   private readonly ObservableAsPropertyHelper<DateTime?> _result;

   [Reactive]
   public DateTime Start { get; set; } = DateTime.Now;

   [Reactive]
   public int Days { get; set; } = 1;

   public DateTime? Result => _result.Value;

   public ReactiveCommand<Unit, DateTime?> CalculateCommand { get; }

   public ReactiveCommand<Unit, Unit> ResetCommand { get; }

   public VM()
   {
      CalculateCommand = ReactiveCommand
        .CreateFromTask<Unit, DateTime?>((_, cancellationToken) => CalculateAsync(cancellationToken));

      _result = CalculateCommand.ToProperty(this, nameof(Result));

      // everything above this works.

      ResetCommand = ReactiveCommand.Create(() =>
      {
          Start = DateTime.Now;
          Days = 1;
          // how do I reset "_result" or "Result" back to null???
      });
   }
 
   private Task<DateTime?> CalculateAsync(CancellationToken _)
   {
      // to be replaced by an API call later.
      return Task.FromResult<DateTime?>(Start.AddDays(Days));
   }

}

How do I reset a value backed by an instance of ObservableAsPropertyHelper?


Solution

  • Figured this out myself:

    namespace WpfApp4;
    using System.Reactive.Linq;
    using System.Threading.Tasks;
    
    using ReactiveUI;
    
    using System;
    using System.Reactive;
    
    public class MainViewModel : ReactiveObject
    {
    
        public ReactiveCommand<Unit, DateTime?> StartCommand { get; }
    
        public ReactiveCommand<Unit, DateTime?> ResetCommand { get; }
    
        private DateTime _start = DateTime.Now;
    
        private int _processingDays = 1;
    
        private readonly ObservableAsPropertyHelper<DateTime?> _result;
    
        public DateTime? Result => _result.Value;
    
        public DateTime Start
        {
            get => _start;
            set => this.RaiseAndSetIfChanged(ref _start, value);
        }
    
        public int ProcessingDays
        {
            get => _processingDays;
            set => this.RaiseAndSetIfChanged(ref _processingDays, value);
        }
    
        public MainViewModel()
        {
            StartCommand = ReactiveCommand.CreateFromTask<DateTime?>(() => Task.FromResult<DateTime?>(Start.AddDays(ProcessingDays)));
    
            ResetCommand = ReactiveCommand.Create<DateTime?>(execute: () => null);
    
            _ = ResetCommand.Subscribe(onNext: (_) =>
              {
                  Start = DateTime.Now;
    
                  ProcessingDays = 1;
              });
    
            _result = StartCommand.Merge(ResetCommand).ToProperty(this, nameof(Result));
        }
    }