Esempio n. 1
0
        internal MainWindowViewModel(AppController controller)
        {
            this._controller = controller ?? throw new ArgumentNullException(nameof(controller));

            Profiles = _controller.Profiles
                       .ToReadOnlyReactiveCollection(x => new ProfileItemViewModel(_controller, x))
                       .AddTo(this.Subscription);
            Profiles
            .ObserveElementObservableProperty(x => x.Position)
            .Throttle(TimeSpan.FromMilliseconds(10))
            .ObserveOn(SynchronizationContext.Current)
            .Subscribe(_ => ProfilesView.Refresh())                     // ListCollectionView.Refresh method seems not thread-safe.
            .AddTo(this.Subscription);

            OrganizesPriority = new ReactiveProperty <bool>()
                                .AddTo(this.Subscription);

            ShowsAvailable = Settings.Current.ToReactivePropertyAsSynchronized(x => x.ShowsAvailable)
                             .AddTo(this.Subscription);
            ShowsAvailable
            .Subscribe(_ => ManageFilter())
            .AddTo(this.Subscription);

            IsUpdating = _controller.IsUpdating
                         .Where(_ => !_controller.IsWorking.Value)
                         //.Select(x => Observable.Empty<bool>()
                         //	.Delay(TimeSpan.FromMilliseconds(10))
                         //	.StartWith(x))
                         //.Concat()
                         .ObserveOnUIDispatcher()
                         .ToReadOnlyReactiveProperty()
                         .AddTo(this.Subscription);

            #region Work

            var isNotWorking = _controller.IsWorking
                               .Inverse()
                               .StartWith(true)  // This is necessary to start combined sequence.
                               .Publish();

            var selectedProfile = Profiles
                                  .ObserveElementObservableProperty(x => x.IsSelected)
                                  .Where(x => x.Value)
                                  .Select(x => x.Instance)
                                  .Publish();

            var canProfileMovedUp = selectedProfile
                                    .Select(x => x.Position.Value > 0);

            MoveUpCommand = new[] { isNotWorking, canProfileMovedUp }
            .CombineLatestValuesAreAllTrue()
            .ObserveOnUIDispatcher()                     // This is for thread access by ReactiveCommand.
            .ToReactiveCommand();
            MoveUpCommand
            .Subscribe(async _ => await _controller.MoveUpProfileAsync())
            .AddTo(this.Subscription);

            var canProfileMovedDown = selectedProfile
                                      .Select(x => x.Position.Value < x.PositionCount.Value - 1);

            MoveDownCommand = new[] { isNotWorking, canProfileMovedDown }
            .CombineLatestValuesAreAllTrue()
            .ObserveOnUIDispatcher()                     // This is for thread access by ReactiveCommand.
            .ToReactiveCommand();
            MoveDownCommand
            .Subscribe(async _ => await _controller.MoveDownProfileAsync())
            .AddTo(this.Subscription);

            var canProfileDeleted = selectedProfile
                                    .Select(x => x.IsConnected)
                                    .Switch()
                                    .Inverse();

            CanDelete = new[] { isNotWorking, canProfileDeleted }
            .CombineLatestValuesAreAllTrue()
            .ObserveOnUIDispatcher()                     // This is for thread access by ReactiveCommand.
            .ToReadOnlyReactiveProperty()
            .AddTo(this.Subscription);

            DeleteCommand = CanDelete
                            .ToReactiveCommand();
            DeleteCommand
            .Subscribe(async _ => await _controller.DeleteProfileAsync())
            .AddTo(this.Subscription);

            isNotWorking.Connect().AddTo(this.Subscription);
            selectedProfile.Connect().AddTo(this.Subscription);

            #endregion
        }
Esempio n. 2
0
        public MainWindowViewModel()
        {
            Op = new Operation(
                //new MockWorker() ??
                //new NetshWorker() ??
                new NativeWifiWorker() as IWlanWorker);

            this.Profiles = Op.Profiles.ToReadOnlyReactiveCollection(x => new ProfileItemViewModel(x));

            #region AutoReloadEnabled/Suspended/ConfigMode

            IsAutoReloadEnabled = Op
                                  .ToReactivePropertyAsSynchronized(x => x.IsAutoReloadEnabled);

            IsSuspended = Op
                          .ToReactivePropertyAsSynchronized(x => x.IsSuspended);

            IsConfigMode = new ReactiveProperty <bool>();

            IsAutoReloadEnabled
            .Merge(IsSuspended)
            .Where(x => x)
            .Subscribe(_ => IsConfigMode.Value = false);

            IsConfigMode
            .Where(x => x)
            .Subscribe(_ => IsAutoReloadEnabled.Value = false);

            #endregion

            #region Load

            IsLoading = Op.IsLoading
                        .Where(_ => !Op.IsWorking.Value)
                        //.Select(x => Observable.Empty<bool>()
                        //	.Delay(TimeSpan.FromMilliseconds(10))
                        //	.StartWith(x))
                        //.Concat()
                        .ObserveOnUIDispatcher()
                        .ToReadOnlyReactiveProperty();

            ReloadCommand = IsLoading
                            .Select(x => !x)
                            .ToReactiveCommand();
            ReloadCommand
            .Subscribe(async _ => await Op.LoadProfilesAsync(true));

            Profiles
            .ObserveElementObservableProperty(x => x.Position)
            .Throttle(TimeSpan.FromMilliseconds(10))
            .ObserveOn(SynchronizationContext.Current)
            .Subscribe(_ => ProfilesView.Refresh());                     // ListCollectionView.Refresh method seems not thread-safe.

            #endregion

            #region Work

            IsNotWorking = Op.IsWorking
                           .Select(x => !x)
                           .StartWith(true)      // This is necessary for initial query.
                           .ObserveOnUIDispatcher()
                           .ToReadOnlyReactiveProperty();

            // Query for a profile which is selected.
            var querySelectedProfiles = Profiles
                                        .ObserveElementObservableProperty(x => x.IsSelected)
                                        .Where(x => x.Value)
                                        .Select(x => x.Instance)
                                        .Publish();

            // Query for the selected profile which is connected or disconnected.
            var queryConnectedProfiles = Profiles
                                         .ObserveElementObservableProperty(x => x.IsConnected)
                                         .Where(x => x.Instance.IsSelected.Value)
                                         .Select(x => x.Instance)
                                         .Publish();

            // Query for the selected profile which changes to be available or unavailable.
            var queryAvailableProfiles = Profiles
                                         .ObserveElementObservableProperty(x => x.IsAvailable)
                                         .Where(x => x.Instance.IsSelected.Value)
                                         .Select(x => x.Instance)
                                         .Publish();

            #region MoveUp

            var queryMoveUp = querySelectedProfiles
                              .Select(x => x.Position.Value > 0);

            MoveUpCommand = new[] { IsNotWorking, queryMoveUp }
            .CombineLatestValuesAreAllTrue()
            .ToReactiveCommand();
            MoveUpCommand
            .Subscribe(async _ => await Op.MoveUpProfileAsync());

            #endregion

            #region MoveDown

            var queryMoveDown = querySelectedProfiles
                                .Select(x => x.Position.Value < x.PositionCount.Value - 1);

            MoveDownCommand = new[] { IsNotWorking, queryMoveDown }
            .CombineLatestValuesAreAllTrue()
            .ToReactiveCommand();
            MoveDownCommand
            .Subscribe(async _ => await Op.MoveDownProfileAsync());

            #endregion

            #region Delete

            DeleteCommand = IsNotWorking
                            .ToReactiveCommand();
            DeleteCommand
            .Subscribe(async _ => await Op.DeleteProfileAsync());

            #endregion

            #region Connect

            var queryConnect = Observable.Merge(querySelectedProfiles, queryConnectedProfiles, queryAvailableProfiles)
                               .Select(x => !x.IsConnected.Value && x.IsAvailable.Value);

            ConnectCommand = new[] { IsNotWorking, queryConnect }
            .CombineLatestValuesAreAllTrue()
            .ToReactiveCommand();
            ConnectCommand
            .Subscribe(async _ => await Op.ConnectNetworkAsync());

            #endregion

            #region Disconnect

            var queryDisconnect = Observable.Merge(querySelectedProfiles, queryConnectedProfiles)
                                  .Select(x => x.IsConnected.Value);

            DisconnectCommand = new[] { IsNotWorking, queryDisconnect }
            .CombineLatestValuesAreAllTrue()
            .ToReactiveCommand();
            DisconnectCommand
            .Subscribe(async _ => await Op.DisconnectNetworkAsync());

            #endregion

            querySelectedProfiles.Connect();
            queryConnectedProfiles.Connect();
            queryAvailableProfiles.Connect();

            #endregion
        }