예제 #1
0
        public AppViewModel(ReactiveAsyncCommand reactiveAsyncCommand       = null,
                            IObservable <List <FlickrPhoto> > searchResults = null)
        {
            ExecuteSearch = reactiveAsyncCommand ?? new ReactiveAsyncCommand();
            ReactiveCommandMixins.InvokeCommand(this.ObservableForProperty(model => model.SearchTerm)
                                                .Throttle(TimeSpan.FromMilliseconds(800), RxApp.TaskpoolScheduler)
                                                .Select(x => x.Value)
                                                .DistinctUntilChanged()
                                                .Where(x => !string.IsNullOrWhiteSpace(x)), ExecuteSearch);
            _spinnerVisibility =
                ExecuteSearch.ItemsInflight.Select(x => x > 0 ? Visibility.Visible : Visibility.Collapsed)
                .ToProperty(this, model => model.SpinnerVisibility, Visibility.Hidden);
            var results = searchResults ??
                          ExecuteSearch.RegisterAsyncFunction(term => GetSearchResultFromFlickr((string)term));

            _searchResults = results.ToProperty(this, model => model.SearchResults, new List <FlickrPhoto>());
        }
        public AppViewModel(ReactiveAsyncCommand testExecuteSearchCommand = null, IObservable <List <FlickrPhoto> > testSearchResults = null)
        {
            ExecuteSearch = testExecuteSearchCommand ?? new ReactiveAsyncCommand();

            /* Creating our UI declaratively
             *
             * The Properties in this ViewModel are related to each other in different
             * ways - with other frameworks, it is difficult to describe each relation
             * succinctly; the code to implement "The UI spinner spins while the search
             * is live" usually ends up spread out over several event handlers.
             *
             * However, with RxUI, we can describe how properties are related in a very
             * organized clear way. Let's describe the workflow of what the user does in
             * this application, in the order they do it.
             */

            // We're going to take a Property and turn it into an Observable here - this
            // Observable will yield a value every time the Search term changes (which in
            // the XAML, is connected to the TextBox).
            //
            // We're going to use the Throttle operator to ignore changes that
            // happen too quickly, since we don't want to issue a search for each
            // key pressed! We then pull the Value of the change, then filter
            // out changes that are identical, as well as strings that are empty.
            //
            // Finally, we use RxUI's InvokeCommand operator, which takes the String
            // and calls the Execute method on the ExecuteSearch Command, after
            // making sure the Command can be executed via calling CanExecute.
            this.ObservableForProperty(x => x.SearchTerm)
            .Throttle(TimeSpan.FromMilliseconds(800), RxApp.DeferredScheduler)
            .Select(x => x.Value)
            .DistinctUntilChanged()
            .Where(x => !String.IsNullOrWhiteSpace(x))
            .InvokeCommand(ExecuteSearch);


            // How would we describe when to show the spinner in English? We
            // might say something like, "The spinner's visibility is whether
            // the search is running". RxUI lets us write these kinds of
            // statements in code.
            //
            // ExecuteSearch has an IObservable<int> called ItemsInFlight that
            // fires every time a new item starts or stops. We Select() that into
            // a Visibility (0 = Collapsed, > 0 = Visible), then we will use RxUI's
            // ToProperty operator, which is a helper to create an
            // ObservableAsPropertyHelper object.
            //
            // Essentially, we're saying here, "The value of SpinnerVisibility is
            // the in-flight items Selected into a Visibility"
            _SpinnerVisibility = ExecuteSearch.ItemsInflight
                                 .Select(x => x > 0 ? Visibility.Visible : Visibility.Collapsed)
                                 .ToProperty(this, x => x.SpinnerVisibility, Visibility.Hidden);

            // Here, we're going to actually describe what happens when the Command
            // gets invoked - we're going to run the GetSearchResultsFromFlickr every
            // time the Command is executed.
            //
            // The important bit here is the return value - an Observable. We're going
            // to end up here with a Stream of FlickrPhoto Lists: every time someone
            // calls Execute, we eventually end up with a new list.

            IObservable <List <FlickrPhoto> > results;

            if (testSearchResults != null)
            {
                results = testSearchResults;
            }
            else
            {
                results = ExecuteSearch.RegisterAsyncFunction(term => GetSearchResultsFromFlickr((string)term));
            }

            // ...which we then immediately put into the SearchResults Property.
            _SearchResults = results.ToProperty(this, x => x.SearchResults, new List <FlickrPhoto>());
        }