public RenameFileViewModel(RenameFileState state, ICloudViewModel owner, ICloud provider) { _oldName = owner .WhenAnyValue(x => x.SelectedFile.Name) .ToProperty(this, x => x.OldName); this.ValidationRule( x => x.NewName, name => !string.IsNullOrWhiteSpace(name), "New name shouldn't be empty."); var oldRule = this.ValidationRule( x => x.OldName, name => !string.IsNullOrWhiteSpace(name), "Old name shouldn't be empty."); Rename = ReactiveCommand.CreateFromTask( () => provider.RenameFile(owner.SelectedFile.Path, NewName), this.IsValid()); _isLoading = Rename .IsExecuting .ToProperty(this, x => x.IsLoading); var canInteract = owner .WhenAnyValue(x => x.CanInteract) .Skip(1) .StartWith(true); var canOpen = this .WhenAnyValue(x => x.IsVisible) .Select(visible => !visible) .CombineLatest( canInteract, oldRule.WhenAnyValue(x => x.IsValid), (visible, interact, old) => visible && old && interact); var canClose = this .WhenAnyValue(x => x.IsVisible) .Select(visible => visible); Open = ReactiveCommand.Create(() => { }, canOpen); Close = ReactiveCommand.Create(() => { }, canClose); Open.Select(unit => true) .Merge(Close.Select(unit => false)) .Subscribe(visible => IsVisible = visible); Close.Subscribe(x => NewName = string.Empty); Rename.InvokeCommand(Close); _hasErrorMessage = Rename .ThrownExceptions .Select(exception => true) .Merge(Close.Select(x => false)) .ToProperty(this, x => x.HasErrorMessage); _errorMessage = Rename .ThrownExceptions .Select(exception => exception.Message) .Log(this, $"Rename file error occured in {provider.Name} for {OldName}") .Merge(Close.Select(x => string.Empty)) .ToProperty(this, x => x.ErrorMessage); NewName = state.NewName; this.WhenAnyValue(x => x.NewName) .Subscribe(name => state.NewName = name); }