RxUI.NET - Hiding a message after a period of time

Viewed 288

I'm toying with Reactive UI and I'd like to show a message after a process is completed and hide this message after a period of time (4 sec). If the messages keep coming faster than is the period for hiding, the timeout should be reset, so the message is always hidden after 4 seconds after the last message is displayed/updated. The hiding should be also prolonged if the last message is the same as previous.

Currently I have this code, which does what I want, but it looks too cumbersome to me. I'm just experimenting with the RxUI, so most of the time I don't know what I'm doing. Are there better ways how to achieve this?

public class MainViewModel: ReactiveObject
{
  // Message to be shown.
  private string message;
  public string Message { get => message; set => this.RaiseAndSetIfChanged(ref message, value);

  // Flag for the UI, if the message panel should be visible.
  private ObservableAsPropertyHelper<bool> isMessageVisible;
  public bool IsMessageVisible => isMessageVisible.Value;

  // Command that runs async process, the result is the message to be shown.
  public ReactiveCommand<Unit, string> Run { get; private set; }  

  public MainViewModel()
  {        
    var msg = this.WhenAnyValue(x => x.Message, x => !string.IsNullOrEmpty(x));

    // If message changes, after 4 seconds return false, causing hiding the message panel.
    var hide = msg.Select(x => false).Throttle(TimeSpan.FromSeconds(4), RxApp.MainThreadScheduler);

    // Merge both sequences into one output property.
    Observable.Merge(msg, hide).ToProperty(this, x => x.IsMessageVisible, out isMessageVisible);

    Run = ReactiveCommand.CreateFromObservable(() => Observable.StartAsync(Process));

    // Merge various message sources and set message property. Set Message = null to force property change.
    Observable.Merge(Run, Run.ThrownExceptions.Select(x => x.Message)).Subscribe(x => { Message = null; Message = x; });      
  }    
  ...
}
1 Answers
Related