Beispiel #1
0
 private void OnNavigationFailed(NavigationFailedEventArgs e)
 {
     NavigationFailed?.Invoke(this, e);
 }
Beispiel #2
0
        private void Navigate(Uri oldValue, Uri newValue, NavigationType navigationType)
        {
            Debug.WriteLine("Navigating from '{0}' to '{1}'", oldValue, newValue);

            // set IsLoadingContent state
            SetValue(IsLoadingContentPropertyKey, true);

            // cancel previous load content task (if any)
            // note: no need for thread synchronization, this code always executes on the UI thread
            if (_tokenSource != null) {
                _tokenSource.Cancel();
                _tokenSource = null;
            }

            // push previous source onto the history stack (only for new navigation types)
            if (oldValue != null && navigationType == NavigationType.New) {
                _history.Push(oldValue);
            }

            object newContent = null;

            if (newValue != null) {
                // content is cached on uri without fragment
                var newValueNoFragment = NavigationHelper.RemoveFragment(newValue);

                if (navigationType == NavigationType.Refresh || !_contentCache.TryGetValue(newValueNoFragment, out newContent)) {
                    var localTokenSource = new CancellationTokenSource();
                    _tokenSource = localTokenSource;
                    // load the content (asynchronous!)
                    var scheduler = TaskScheduler.FromCurrentSynchronizationContext();
                    var task = ContentLoader.LoadContentAsync(newValue, _tokenSource.Token);

                    task.ContinueWith(t => {
                        try {
                            if (t.IsCanceled || localTokenSource.IsCancellationRequested) {
                                Debug.WriteLine("Cancelled navigation to '{0}'", newValue);
                            }
                            else if (t.IsFaulted) {
                                // raise failed event
                                var failedArgs = new NavigationFailedEventArgs {
                                    Frame = this,
                                    Source = newValue,
                                    Error = t.Exception?.InnerException,
                                    Handled = false
                                };

                                OnNavigationFailed(failedArgs);

                                // if not handled, show error as content
                                newContent = failedArgs.Handled ? null : failedArgs.Error;

                                SetContent(newValue, navigationType, newContent, true);
                            }
                            else {
                                newContent = t.Result;
                                if (ShouldKeepContentAlive(newContent)) {
                                    // keep the new content in memory
                                    _contentCache[newValueNoFragment] = newContent;
                                }

                                SetContent(newValue, navigationType, newContent, false);
                            }
                        }
                        finally {
                            // clear global tokenSource to avoid a Cancel on a disposed object
                            if (_tokenSource == localTokenSource) {
                                _tokenSource = null;
                            }

                            // and dispose of the local tokensource
                            localTokenSource.Dispose();
                        }
                    }, scheduler);
                    return;
                }
            }

            // newValue is null or newContent was found in the cache
            SetContent(newValue, navigationType, newContent, false);
        }