예제 #1
0
        public MainViewModel(IAppEventObservable appEvents)
        {
            // Tomamos un C# event y lo convertimos a un Observable.
            // Este Observable retornara el estado de la conneccion a Internet
            var isConnected = Observable.FromEventPattern <ConnectivityChangedEventArgs>
                                  (h => Connectivity.ConnectivityChanged += h,
                                  h => Connectivity.ConnectivityChanged  -= h)
                              .Select(IsDeviceConnected);

            // Observamos cuando el valor de la propiedad `Name` cambie usando `WhenAnyValue`
            var nameChanged = this.WhenAnyValue(x => x.Name)
                              .Throttle(TimeSpan.FromMilliseconds(100), RxApp.MainThreadScheduler);

            // Observamos cuando el valor de la propiedad `LastName` cambie usando `WhenAnyValue`
            var lastNameChanged = this.WhenAnyValue(x => x.LastName)
                                  .Throttle(TimeSpan.FromMilliseconds(100), RxApp.MainThreadScheduler);

            // Tomamos 3 Observables distintos y lo combinamos usando CombineLatest.
            // El Observable resultante es un IObservable<bool> el cual decidira si un Commando se puede ejecutar.
            // Para el isConnected tenemos que usar `StartWith` ya que este Observable no nos va a notificar hasta cuando
            // ocurra un cambio en la conneccion pero necesitamos el estado actual.
            var canExecuteCreate = isConnected.StartWith(GetCurrentNetworkState())
                                   .CombineLatest(nameChanged, lastNameChanged,
                                                  (connected, name, lastName) => !string.IsNullOrWhiteSpace(name) &&
                                                  !string.IsNullOrWhiteSpace(lastName) && connected);

            // Creamos un ReactiveCommand al cual usara como `canExecute` el Observable `canExecuteCreate`
            // Esto hara que cuando haya un cambio en cualquiera de los observables de ese pipeline este Commando reacionara a esto.
            CreateCommand = ReactiveCommand.CreateFromTask(ExecuteCreate, canExecuteCreate);

            // Creamos un segundo ReactiveCommand
            SubmitCommand = ReactiveCommand.Create(ExecuteSubmit);

            var isAppInBackground = appEvents.IsInBackground();

            // Combinamos dos observables y el observable resultante lo llevamos a un
            // OAPH utilizando `ToProperty`
            var changed = nameChanged.CombineLatest(lastNameChanged,
                                                    (name, lastName) => $"{lastName}, {name}")
                          .ToProperty(this, nameof(FullName), out _fullName)
                          .DisposeWith(ViewModelSubscriptions);

            // Nos subscribimos al pipelione del ReactiveCommand y cuando este completa
            // invocamos un segundo ReactiveCommand utilizando `InvokeCommand`
            CreateCommand
            .Select(a => Unit.Default)
            .InvokeCommand(SubmitCommand)
            .DisposeWith(ViewModelSubscriptions);

            // Nos subscribimos al pipelione del ReactiveCommand y si ocurre una Exception durante su ejecucion
            // nos subscribimos a ella
            CreateCommand
            .ThrownExceptions
            .Subscribe(error =>
            {
                // Aqui podemos actual en base al error
            })
            .DisposeWith(ViewModelSubscriptions);

            //Tomando el resultado del ReactiveCommand y lo llevamos un OAPH utilizando `ToProperty`
            CreateCommand.ToProperty(this, nameof(LatestDocumentId), out _latestDocId);

            // Muestra de como podemos invocar un RactiveCommand desde cualquier Pipeline
            nameChanged
            .Where(x => x == "ReactiveUI")
            .Select(x => Unit.Default)
            .InvokeCommand(CreateCommand);

            // Podemos subscribirnos al Observable IsExecuting del Commando para verificar el estado de la ejecucion.
            SubmitCommand.IsExecuting
            .CombineLatest(CreateCommand.IsExecuting, (submitIsExecuting, createIsExecuting) => !submitIsExecuting && !createIsExecuting)
            .Skip(1)
            .Where(isExecuting => !isExecuting)
            .DistinctUntilChanged()
            .Subscribe(x =>
            {
                // Aqui tenemos acceso a ejecutar cualquier accion o cambiar el valor de alguna propiedad.
                // Pero si ese es el caso mejor evaluas hacerlo con `InvokeCommand` o `ToProperty` dependiendo
                // Cual sea tu necesidad. Aqui solo te mostramos que es posible.
            })
            .DisposeWith(ViewModelSubscriptions);

            var timedHasPassed = Observable.Interval(TimeSpan.FromMinutes(15));

            // Tomamos 3 Observables y le hacer Merge. Cuando alguno de estos 3 Observables de este Pipeline
            // notifique y las condiciones se den se ejecutra el metodo dentro del Subscribe.
            isConnected.Where(connected => !connected)
            .Merge(isAppInBackground.Where(isInBackground => isInBackground))
            .Merge(timedHasPassed.Select(a => true))            //Merge necesita que todos los Observables sean del mismo tipo
            .Subscribe(StopLongRunningService)
            .DisposeWith(ViewModelSubscriptions);
        }