public async Task Change(Route route) { SynchronizationContext.VerifyAccess(); if (route == null) { throw new ArgumentNullException(nameof(route)); } if (route == Current) { return; } if (route.Routes != null && route.Routes != this) { throw new ArgumentException(ErrorMessages.RoutesAssociatedWithOtherStack); } var completionSources = new List <TaskCompletionSource <object> >(stack.Count); var errors = new List <RouteEventError>(); using (Lock) { await ChangeRoute(route, completionSources, errors); } await OnRouteReady(route, RouteActivationMethod.Changed, errors); foreach (var completionSource in completionSources) { completionSource.SetCanceled(); } }
public async Task <object> Push(Route route, bool cacheCurrentView) { SynchronizationContext.VerifyAccess(); if (route == null) { throw new ArgumentNullException(nameof(route)); } if (route.Routes != null && route.Routes != this) { throw new ArgumentException(ErrorMessages.RoutesAssociatedWithOtherStack); } if (route is TransientRoute) { throw new ArgumentException("Cannot push a transient route."); } if (stack.Any(item => item.Route == route)) { throw new InvalidOperationException("Cannot push same route instance multiple times."); } List <RouteEventError> errors; Task <object> result; using (Lock) { errors = new List <RouteEventError>(); result = (await PushRoute(route, cacheCurrentView, false, errors)).Task; } await OnRouteReady(route, RouteActivationMethod.Pushed, errors); return(await result); }
public async Task <Route> Pop(object result) { SynchronizationContext.VerifyAccess(); if (stack.Count <= 1) { throw new InvalidOperationException("Cannot pop base route."); } RouteItem poppedRoute; RouteItem nextRoute; List <RouteEventError> errors; using (Lock) { poppedRoute = stack.Pop(); nextRoute = stack.Peek(); errors = new List <RouteEventError>(); try { await poppedRoute.Route.OnRouteDeactivating(false); } catch (Exception ex) { RouteErrorListener.TryOnRouteEventException(poppedRoute.Route, RouteEventType.Deactivating, ex); } try { await nextRoute.Route.OnRouteRestoring(result); } catch (Exception ex) { errors.Add(new RouteEventError(RouteEventType.Restoring, ex)); RouteErrorListener.TryOnRouteEventException(nextRoute.Route, RouteEventType.Restoring, ex); } poppedRoute.CachedView = null; var route = nextRoute.Route; if (nextRoute.CachedView == null) { try { var view = route.CreateView(false); nextRoute.CachedView = view; var frameworkElement = view as FrameworkElement; if (frameworkElement != null && frameworkElement.DataContext == null) { frameworkElement.DataContext = route; } } catch (Exception ex) { errors.Add(new RouteEventError(RouteEventType.ViewCreation, ex)); RouteErrorListener.TryOnRouteEventException(route, RouteEventType.ViewCreation, ex); } } RouteHead = nextRoute; try { await poppedRoute.Route.OnRouteDeactivated(false); } catch (Exception ex) { RouteErrorListener.TryOnRouteEventException(poppedRoute.Route, RouteEventType.Deactivated, ex); } try { await nextRoute.Route.OnRouteRestored(result); } catch (Exception ex) { errors.Add(new RouteEventError(RouteEventType.Restored, ex)); RouteErrorListener.TryOnRouteEventException(nextRoute.Route, RouteEventType.Restored, ex); } } await OnRouteReady(nextRoute.Route, RouteActivationMethod.Restored, errors); poppedRoute.CompletionSource.SetResult(result); return(nextRoute.Route); }