public async Task UpdateNavigation(NavigationOperation <TViewModel> navigationOperation, INavigationInProgress navigationInProgress) { if (navigationOperation.Pushes.Count == 0 && navigationOperation.Pops.Count == 0) { return; } var controllersToPush = navigationOperation.Pushes.Select(x => new PushInformation <TViewModel>(_factoryAssociation[x.Screen], x.Instance)).ToList(); foreach (var push in navigationOperation.Pushes) { await push.Instance.GetViewModel(""); //TODO: add route here } if (navigationInProgress.IsCancelled) { Task.Run(async() => { // we wait 10s just in case, shouldn't put too much memory pressure on GC await Task.Delay(10_000); foreach (var push in navigationOperation.Pushes) { push.Instance.ViewModelInstance?.SafeDispose(); } }).ConfigureAwait(false); return; } navigationInProgress.Commit(); CrossCurrentActivity.Current.Activity.RunOnUiThread(() => _navigationStack.ApplyActions(navigationOperation.Pops.Count, controllersToPush)); }
public INavigationOperation TryShowAsync(IViewModel viewModel, IDataContext context, IViewModelPresenter parentPresenter) { if (!CanShowViewModel(viewModel, context, parentPresenter)) { return(null); } var tcs = new TaskCompletionSource <object>(); var operation = new NavigationOperation(tcs.Task); context = context.ToNonReadOnly(); context.AddOrUpdate(NavigationConstants.ViewModel, viewModel); var provider = viewModel.GetIocContainer(true).Get <INavigationProvider>(); provider.CurrentNavigationTask.TryExecuteSynchronously(_ => { try { var task = provider.NavigateAsync(operation.ToOperationCallback(), context); tcs.TrySetFromTask(task); } catch (Exception e) { tcs.TrySetException(e); throw; } }); return(operation); }
public virtual INavigationOperation TryShowAsync(IViewModel viewModel, IDataContext context, IViewModelPresenter parentPresenter) { if (!MultiViewModel.ViewModelType.IsInstanceOfType(viewModel)) { return(null); } bool data; if (context.TryGetData(NavigationConstants.SuppressTabNavigation, out data) && data) { return(null); } if (!CanShowViewModel(viewModel, context, parentPresenter)) { return(null); } if (MultiViewModel.ItemsSource.Any(vm => vm == viewModel)) { MultiViewModel.SelectedItem = viewModel; } else { MultiViewModel.AddViewModel(viewModel, true); } var operation = new NavigationOperation(); CallbackManager.Register(OperationType.TabNavigation, viewModel, operation.ToOperationCallback(), context); return(operation); }
public Task UpdateNavigation(NavigationOperation <SampleViewModel> navigationOperation, INavigationInProgress navigationInProgress) { Console.WriteLine($"\tOperations to apply: Pops={navigationOperation.Pops.Count}, Pushes={navigationOperation.Pushes.Count}"); Console.WriteLine(""); navigationInProgress.Commit(); return(Task.CompletedTask); }
public async Task UpdateNavigation(NavigationOperation <TViewModel> navigationOperation, INavigationInProgress navigationInProgress) { if (navigationOperation.Pushes.Count == 0 && navigationOperation.Pops.Count == 0) { return; } var controllersToPush = navigationOperation.Pushes.Select(x => new PushInformation <TViewModel>(_factoryAssociation[x.Screen], x.Instance)); foreach (var push in navigationOperation.Pushes) { await push.Instance.GetViewModel(""); //TODO: add route here } if (navigationInProgress.IsCancelled) { Task.Run(async() => { // we wait 10s just in case, shouldn't put too much memory pressure on GC await Task.Delay(10_000); foreach (var push in navigationOperation.Pushes) { push.Instance.ViewModelInstance?.SafeDispose(); } }).ConfigureAwait(false); return; } navigationInProgress.Commit(); UIApplication.SharedApplication.InvokeOnMainThread(() => { var callbackActionWaiter = new CallbackActionWaiter(); callbackActionWaiter.WaitOne(); _navigationStack.EnsureInitialized(_navigationController); _navigationStack.ApplyActions(navigationOperation.Pops.Count, controllersToPush, callbackActionWaiter); // lines below could be commented if we encounter issues with viewmodel disposing callbackActionWaiter.Add(() => { foreach (PopAction <TViewModel> pop in navigationOperation.Pops) { pop.Instance.ViewModelInstance?.DispatchSafeDispose(); } }); Task.Run(async() => { // we wait 10s to let the time for navigation controller animations before disposing content await Task.Delay(10_000); UIApplication.SharedApplication.InvokeOnMainThread(callbackActionWaiter.ReleaseOne); }); }); }
private void Journal_Navigated(object sender, JournalEventArgs args) { if (this._journalIsAddingHistoryPoint == false) { NavigationOperation navOp = this._currentNavigation; if (navOp == null || navOp.SuppressNotifications == false) { this.NavigateCore(args.Uri, args.NavigationMode, true /*suppressJournalAdd*/, false /*isRedirect*/); } } }
/// <summary> /// StopLoading aborts asynchronous navigations that haven't been processed yet. /// The <see cref="NavigationStopped"/> event is raised only if the navigation was actually aborted - if navigation is /// too far along to be canceled, then navigation may still complete and the <see cref="Navigated"/> event /// will be raised. /// </summary> /// <value></value> public void StopLoading() { NavigationOperation navOp = this._currentNavigation; if (navOp != null) { this.RaiseNavigationStopped(null, navOp.Uri); // Release current context this._currentNavigation = null; } }
private void ContentLoader_BeginLoad_Callback(IAsyncResult result) { DependencyObject content = null; Uri uriBeingLoaded = null; try { NavigationOperation asyncNavigationOperationCompleted = result.AsyncState as NavigationOperation; NavigationOperation navOp = this._currentNavigation; if (navOp == null || navOp.Uri != asyncNavigationOperationCompleted.Uri) { // We already fired NavigationStopped in NavigateCore(), so just return without doing anything return; } uriBeingLoaded = navOp.UriBeforeMapping; content = this._contentLoader.EndLoad(result) as DependencyObject; // If the content is anything but a UserControl, we should throw. // We support UserControls as they are a typical thing created in designers such as Blend, // but for a full experience one would use Page to get to things like NavigationContext, // NavigationService, Title, etc. if (!(content is UserControl)) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, Resource.NavigationService_ContentIsNotAUserControl, content == null ? "null" : content.GetType().ToString(), "System.Windows.Controls.UserControl")); } // Content loader was successful, so complete navigation // Create a new navigation context JournalEntry.SetNavigationContext(content, new NavigationContext(UriParsingHelper.InternalUriParseQueryStringToDictionary(asyncNavigationOperationCompleted.Uri, true /* decodeResults */))); content.SetValue(NavigationServiceProperty, this); // Complete navigation operation this.CompleteNavigation(content); } catch (Exception ex) { if (this.RaiseNavigationFailed(uriBeingLoaded, ex)) { throw; } } }
public INavigationOperation TryShowAsync(IViewModel viewModel, IDataContext context, IViewModelPresenter parentPresenter) { if (viewModel == this) { return(null); } var operation = new NavigationOperation(); var callback = operation.ToOperationCallback(); //Saving callback to view model state that will allow us to execute it even after app save\restore cycle. _callbackManager.Register(NavigationType, viewModel, callback, context); OnShowViewModel(viewModel); return(operation); }
private void StopLoadingCore(bool fromRedirect) { NavigationOperation navOp = this._currentNavigation; if (navOp != null) { if (!fromRedirect) { // We don't want to call CancelLoad for redirects this.ContentLoader.CancelLoad(navOp.AsyncResult); } this.RaiseNavigationStopped(null, navOp.Uri); // Release current context this._currentNavigation = null; } }
private bool NavigateCore_StartNavigation(Uri uri, NavigationMode mode, bool suppressJournalAdd, Uri mergedUriAfterMapping, Uri mergedUri, bool isFragmentNavigationOnly) { this._currentNavigation = new NavigationOperation(mergedUriAfterMapping, mergedUri, uri, mode, suppressJournalAdd); if (isFragmentNavigationOnly) { // If we're navigating only to a fragment (e.g. "#frag2") then the Uri to journal should be that merged with the base uri if (UriParsingHelper.InternalUriIsFragment(uri)) { this._currentNavigation.UriForJournal = mergedUri; } this.Host.Dispatcher.BeginInvoke(() => this.CompleteNavigation(null)); return(true); } this.UpdateNavigationCacheModeAlwaysPages(); string uriAllButFragment = UriParsingHelper.InternalUriGetAllButFragment(uri); Page reusedPage = null; if (this._cacheRequiredPages.ContainsKey(uriAllButFragment)) { reusedPage = this._cacheRequiredPages[uriAllButFragment]; } else if (this.Cache.Contains(uriAllButFragment)) { reusedPage = this.Cache[uriAllButFragment]; } // If a page was found in either cache and that page hasn't yet changed its NavigationCacheMode to Disabled, // then navigation is done, otherwise open up new content if (reusedPage != null && reusedPage.NavigationCacheMode != NavigationCacheMode.Disabled) { this.Host.Dispatcher.BeginInvoke(() => this.CompleteNavigation(reusedPage)); } else { this._currentNavigation.AsyncResult = this._contentLoader.BeginLoad(mergedUriAfterMapping, this._currentSourceAfterMapping, this.ContentLoader_BeginLoad_Callback, this._currentNavigation); } return(true); }
protected Mock <IEditorWrapperViewModel> SetupEditableWrapper(bool result, Action <IViewModel> wrapCallback = null) { var wrapper = new Mock <IEditorWrapperViewModel>(); WrapperManagerMock .Setup(provider => provider.Wrap(It.IsAny <IViewModel>(), typeof(IEditorWrapperViewModel), It.IsAny <IDataContext>())) .Returns <IViewModel, Type, IDataContext>((vm, t, context) => { if (wrapCallback != null) { wrapCallback(vm); } return(wrapper.Object); }); var operation = new NavigationOperation(); operation.SetResult(OperationResult.CreateResult(OperationType.PageNavigation, wrapper, result)); ViewModelPresenterMock.Setup(presenter => presenter.ShowAsync(wrapper.Object, It.IsAny <IDataContext>())) .Returns(() => operation); return(wrapper); }
public INavigationOperation TryShowAsync(IViewModel viewModel, IDataContext context, IViewModelPresenter parentPresenter) { var viewMediator = TryCreateWindowViewMediator(viewModel, context); if (viewMediator == null) { return(null); } var tcs = new TaskCompletionSource <object>(); var operation = new NavigationOperation(tcs.Task); if (_currentTask == null) { Show(viewMediator, operation, context, tcs); } else { _currentTask.TryExecuteSynchronously(_ => Show(viewMediator, operation, context, tcs)); } return(operation); }
public void Navigate(NavigationOperation operation) { switch (operation) { case NavigationOperation.NavigateBack: this.Driver.Navigate().Back(); break; case NavigationOperation.NavigateForward: this.Driver.Navigate().Forward(); break; case NavigationOperation.Reload: this.Driver.Navigate().Refresh(); break; default: throw new InvalidOperationException($"The navigation operation '{operation}' is invalid."); } }
public virtual INavigationOperation TryShowAsync(IViewModel viewModel, IDataContext context, IViewModelPresenter parentPresenter) { Should.NotBeNull(viewModel, "viewModel"); if (ReferenceEquals(viewModel, _multiViewModel)) { return(null); } bool data; if (context.TryGetData(NavigationConstants.SuppressTabNavigation, out data) && data) { return(null); } if (!CanShowViewModel(viewModel, context, parentPresenter)) { return(null); } MultiViewModel.AddViewModel(viewModel, true); var operation = new NavigationOperation(); CallbackManager.Register(OperationType.TabNavigation, viewModel, operation.ToOperationCallback(), context); return(operation); }
public virtual INavigationOperation TryShowAsync(IViewModel viewModel, IDataContext context, IViewModelPresenter parentPresenter) { Should.NotBeNull(viewModel, "viewModel"); bool data; if (context.TryGetData(NavigationConstants.SuppressTabNavigation, out data) && data) return null; if (!CanShowViewModel(viewModel, context, parentPresenter)) return null; MultiViewModel.AddViewModel(viewModel, true); var operation = new NavigationOperation(); CallbackManager.Register(OperationType.TabNavigation, viewModel, operation.ToOperationCallback(), context); return operation; }
public INavigationOperation TryShowAsync(IViewModel viewModel, IDataContext context, IViewModelPresenter parentPresenter) { if (!CanShowViewModel(viewModel, context, parentPresenter)) return null; var tcs = new TaskCompletionSource<object>(); var operation = new NavigationOperation(tcs.Task); context = context.ToNonReadOnly(); context.AddOrUpdate(NavigationConstants.ViewModel, viewModel); var provider = viewModel.GetIocContainer(true).Get<INavigationProvider>(); provider.CurrentNavigationTask.TryExecuteSynchronously(_ => { try { var task = provider.NavigateAsync(operation.ToOperationCallback(), context); tcs.TrySetFromTask(task); } catch (Exception e) { tcs.TrySetException(e); throw; } }); return operation; }
private void CompleteNavigation(DependencyObject content) { Uri uri = null; string pageTitle = null; Page existingContentPage = this._host.Content as Page; Page newContentPage = content as Page; pageTitle = JournalEntry.GetName(content ?? this._host.Content as DependencyObject); NavigationOperation navOp = this._currentNavigation; this._currentNavigation = null; if (navOp != null) { // Set uri uri = navOp.UriBeforeMapping; this.UpdateNavigationCacheModeAlwaysPages(); // Used to suppress navigation notifications. navOp.SuppressNotifications = true; this.CurrentSource = navOp.UriForJournal; this._source = navOp.UriBeforeMapping; this._currentSourceAfterMapping = navOp.Uri; this.Host.UpdateSourceFromNavigationService(navOp.UriForJournal); this.Host.CurrentSource = this.CurrentSource; // Check if this is a 'New' operation if (navOp.Mode == NavigationMode.New && navOp.Uri != null && navOp.SuppressJournalAdd == false) { try { this._journalIsAddingHistoryPoint = true; JournalEntry je = new JournalEntry(pageTitle ?? uri.OriginalString, navOp.UriForJournal); this.Journal.AddHistoryPoint(je); } finally { this._journalIsAddingHistoryPoint = false; } } this.Host.CanGoBack = this.CanGoBack; this.Host.CanGoForward = this.CanGoForward; navOp.SuppressNotifications = false; } if (this.Journal.UseNavigationState && HtmlPage.IsEnabled) { HtmlPage.Document.SetProperty("title", pageTitle ?? uri.OriginalString); } if (content == null) { // We're navigating to a fragment in the current page, so for WPF compatibility, fire FragmentNavigation THEN Navigated this.RaiseFragmentNavigation(UriParsingHelper.InternalUriGetFragment(navOp.Uri)); this.RaiseNavigated(content, uri, existingContentPage, newContentPage); } else { // We're navigating to a fragment in the new content, so let the host load content, then for WPF compatibility, // fire Navigated THEN FragmentNavigation this.Host.Content = content; this.RaiseNavigated(content, uri, existingContentPage, newContentPage); string fragment = UriParsingHelper.InternalUriGetFragment(navOp.Uri); if (!String.IsNullOrEmpty(fragment)) { this.RaiseFragmentNavigation(fragment); } } }
private bool NavigateCore_StartNavigation(Uri uri, NavigationMode mode, bool suppressJournalAdd, Uri mergedUriAfterMapping, Uri mergedUri, bool isFragmentNavigationOnly) { this._currentNavigation = new NavigationOperation(mergedUriAfterMapping, mergedUri, uri, mode, suppressJournalAdd); if (isFragmentNavigationOnly) { // If we're navigating only to a fragment (e.g. "#frag2") then the Uri to journal should be that merged with the base uri if (UriParsingHelper.InternalUriIsFragment(uri)) { this._currentNavigation.UriForJournal = mergedUri; } this.Host.Dispatcher.BeginInvoke(() => this.CompleteNavigation(null)); return true; } string uriAllButFragment = UriParsingHelper.InternalUriGetAllButFragment(uri); Page reusedPage = null; if (this._cacheRequiredPages.ContainsKey(uriAllButFragment)) { reusedPage = this._cacheRequiredPages[uriAllButFragment]; } else if (this.Cache.Contains(uriAllButFragment)) { reusedPage = this.Cache[uriAllButFragment]; } // If a page was found in either cache and that page hasn't yet changed its NavigationCacheMode to Disabled, // then navigation is done, otherwise open up new content if (reusedPage != null && reusedPage.NavigationCacheMode != NavigationCacheMode.Disabled) { this.Host.Dispatcher.BeginInvoke(() => this.CompleteNavigation(reusedPage)); } else { this._contentLoader.BeginLoad(mergedUriAfterMapping, this.ContentLoader_BeginLoad_Callback, this._currentNavigation); } return true; }
public INavigationOperation TryShowAsync(IViewModel viewModel, IDataContext context, IViewModelPresenter parentPresenter) { if (viewModel == this) return null; var operation = new NavigationOperation(); var callback = operation.ToOperationCallback(); //Saving callback to view model state that will allow us to execute it even after app save\restore cycle. _callbackManager.Register(NavigationType, viewModel, callback, context); OnShowViewModel(viewModel); return operation; }
public virtual INavigationOperation TryShowAsync(IViewModel viewModel, IDataContext context, IViewModelPresenter parentPresenter) { Should.NotBeNull(viewModel, nameof(viewModel)); if (ReferenceEquals(viewModel, _multiViewModel)) return null; bool data; if (context.TryGetData(NavigationConstants.SuppressTabNavigation, out data) && data) return null; if (!CanShowViewModel(viewModel, context, parentPresenter)) return null; if (MultiViewModel.ItemsSource.Contains(viewModel)) MultiViewModel.SelectedItem = viewModel; else MultiViewModel.AddViewModel(viewModel, true); var operation = new NavigationOperation(); CallbackManager.Register(OperationType.TabNavigation, viewModel, operation.ToOperationCallback(), context); return operation; }
public bool Restore(Type targetType, object target, Dictionary <Type, object> items, ICollection <IViewModel> viewModels, string awaiterResultType, IOperationResult result) { var field = targetType.GetFieldEx(Name, MemberFlags.NonPublic | MemberFlags.Public | MemberFlags.Instance); if (field == null) { TraceError(null, targetType); return(false); } switch (FieldType) { case BuilderField: var type = Type.GetType(TypeName, true); var createMethod = type.GetMethodEx("Create", MemberFlags.NonPublic | MemberFlags.Public | MemberFlags.Static); var startMethod = type.GetMethodEx("Start", MemberFlags.NonPublic | MemberFlags.Public | MemberFlags.Instance); if (createMethod == null || startMethod == null || !startMethod.IsGenericMethodDefinition) { ((IAsyncStateMachine)target).MoveNext(); return(true); } var builder = createMethod.Invoke(null, Empty.Array <object>()); field.SetValueEx(target, builder); startMethod.MakeGenericMethod(typeof(IAsyncStateMachine)) .Invoke(builder, new[] { target }); break; case AwaiterField: var awaiterType = typeof(SerializableAwaiter <>).MakeGenericType(Type.GetType(awaiterResultType, true)); var instance = Activator.CreateInstance(awaiterType, result); field.SetValueEx(target, instance); break; case AsyncOperationField: var opType = typeof(AsyncOperation <>).MakeGenericType(Type.GetType(awaiterResultType, true)); var opInstance = (IAsyncOperation)Activator.CreateInstance(opType); AsyncOperation <object> .TrySetResult(opInstance, result); field.SetValueEx(target, opInstance); break; case AnonymousClass: var anonType = Type.GetType(TypeName, true); object anonClass; if (!items.TryGetValue(anonType, out anonClass)) { anonClass = ServiceProvider.GetOrCreate(anonType); foreach (var snapshot in Snapshots) { snapshot.Restore(anonType, anonClass, items, viewModels, awaiterResultType, result); } items[anonType] = anonClass; } field.SetValueEx(target, anonClass); break; case NavigationOperationField: var operation = new NavigationOperation(); operation.SetResult(OperationResult.Convert <bool>(result)); field.SetValueEx(target, operation); break; case NonSerializableField: object service; if (State == null) { var serviceType = Type.GetType(TypeName, true); if (!items.TryGetValue(serviceType, out service)) { if (field.Name.Contains("CachedAnonymousMethodDelegate")) { service = field.GetValueEx <object>(target); } else if (!ServiceProvider.TryGet(serviceType, out service)) { service = field.GetValueEx <object>(target); TraceError(field, targetType); } items[serviceType] = service; } } else { var restoreValueState = ApplicationSettings.RestoreValueState; service = restoreValueState == null ? State : restoreValueState(State, items, viewModels); } field.SetValueEx(target, service); break; case SerializableField: field.SetValueEx(target, IsType ? Type.GetType((string)State, false) : State); break; case ViewModelField: var viewModel = FindViewModel(viewModels); if (viewModel == null) { TraceError(field, targetType); return(false); } field.SetValueEx(target, viewModel); break; } return(true); }
private void CompleteNavigation(DependencyObject content) { Uri uri = null; string pageTitle = null; Page existingContentPage = this._host.Content as Page; Page newContentPage = content as Page; pageTitle = JournalEntry.GetName(content ?? this._host.Content as DependencyObject); NavigationOperation navOp = this._currentNavigation; this._currentNavigation = null; if (navOp != null) { // Set uri uri = navOp.UriBeforeMapping; // Used to suppress navigation notifications. navOp.SuppressNotifications = true; if (this.CurrentSource == navOp.UriForJournal) { // Do not record the navigation in the journal when moving to the same URI whether this // is a redirection or not. navOp.SuppressJournalAdd = true; } this.CurrentSource = navOp.UriForJournal; this._source = navOp.UriBeforeMapping; this._currentSourceAfterMapping = navOp.Uri; this.Host.UpdateSourceFromNavigationService(navOp.UriForJournal); this.Host.CurrentSource = this.CurrentSource; // Check if this is a 'New' operation if (navOp.Mode == NavigationMode.New && navOp.Uri != null && navOp.SuppressJournalAdd == false) { try { this._journalIsAddingHistoryPoint = true; JournalEntry je = new JournalEntry(pageTitle ?? uri.OriginalString, navOp.UriForJournal); this.Journal.AddHistoryPoint(je); } finally { this._journalIsAddingHistoryPoint = false; } } this.Host.CanGoBack = this.CanGoBack; this.Host.CanGoForward = this.CanGoForward; navOp.SuppressNotifications = false; } if (this.Journal.UseNavigationState && HtmlPage.IsEnabled) { HtmlPage.Document.SetProperty("title", pageTitle ?? (uri == null ? string.Empty : uri.OriginalString)); } if (content == null) { // We're navigating to a fragment in the current page, so for WPF compatibility, fire FragmentNavigation THEN Navigated if (navOp != null) { this.RaiseFragmentNavigation(UriParsingHelper.InternalUriGetFragment(navOp.Uri)); this.RaiseNavigated(content, uri, existingContentPage, newContentPage); } } else { // We're navigating to a fragment in the new content, so let the host load content, then for WPF compatibility, // fire Navigated THEN FragmentNavigation this.Host.Content = content; this.RaiseNavigated(content, uri, existingContentPage, newContentPage); string fragment = navOp == null ? null : UriParsingHelper.InternalUriGetFragment(navOp.Uri); if (!String.IsNullOrEmpty(fragment)) { this.RaiseFragmentNavigation(fragment); } } }
public INavigationOperation TryShowAsync(IViewModel viewModel, IDataContext context, IViewModelPresenter parentPresenter) { var viewMediator = TryCreateWindowViewMediator(viewModel, context); if (viewMediator == null) return null; var tcs = new TaskCompletionSource<object>(); var operation = new NavigationOperation(tcs.Task); if (_currentTask == null) Show(viewMediator, operation, context, tcs); else _currentTask.TryExecuteSynchronously(_ => Show(viewMediator, operation, context, tcs)); return operation; }