예제 #1
0
        private async Task <bool> NavigationOrchestratorAsync(Type page, object parameter, NavigationMode mode, Func <bool> navigate)
        {
            try
            {
                await _navigationOrchestratorAsyncSemaphore.WaitAsync();

                this.Log($"Page: {page}, Parameter: {parameter}, NavigationMode: {mode}");

                if (page == null)
                {
                    throw new ArgumentNullException(nameof(page));
                }

                if (navigate == null)
                {
                    throw new ArgumentNullException(nameof(navigate));
                }

                // this cannot be used for duplicate navigation, except for refresh
                if (!Equals(mode, NavigationMode.Refresh))
                {
                    if (Equals(page, CurrentPageType))
                    {
                        if (Equals(parameter, CurrentPageParam))
                        {
                            return(false);
                        }
                    }
                }

                // fetch current (which will become old)
                var fromPage      = FrameEx.Content as Page;
                var fromParameter = CurrentPageParam;
                var fromViewModel = fromPage?.DataContext;
                var fromPageName  = fromPage?.GetType().ToString();
                var fromPageState = await FrameEx2.GetPageStateAsync(fromPage?.GetType());

                var from = new NavigationInfo(fromPage?.GetType(), fromParameter, fromPageState);

                var toPageName  = page?.ToString();
                var toPageState = await FrameEx2.GetPageStateAsync(toPageName);

                var to = new NavigationInfo(page, parameter, toPageState);

                // call fromViewModel.OnNavigatingFromAsync()
                var NavigatingFromAsyncResult = await ViewModelActionStrategy.NavigatingFromAsync(fromViewModel, mode, false, from, to, this);

                if (NavigatingFromAsyncResult == ContinueResult.Stop)
                {
                    return(false);
                }

                // raise Navigating event
                Two.RaiseNavigatingCancels(parameter, false, mode, to, out var RaiseNavigatingCancelsResult);
                if (RaiseNavigatingCancelsResult == ContinueResult.Stop)
                {
                    return(false);
                }

                // try to resolve the view-model before navigation
                var newViewModel = await ViewModelResolutionStrategy.ResolveViewModelAsync(page);

                if (newViewModel != null)
                {
                    if (newViewModel is ITemplate10ViewModel t)
                    {
                        t.NavigationService = this;
                    }
                    await ViewModelActionStrategy.NavigatingToAsync(newViewModel, mode, false, from, to, this);
                }

                // navigate
                var newPage = default(Page);
                if (navigate.Invoke())
                {
                    if ((newPage = FrameEx.Content as Page) == null)
                    {
                        return(false);
                    }
                    CurrentPageParam = parameter;
                    CurrentPageType  = page;
                }
                else
                {
                    return(false);
                }

                // fetch current (which is now new)
                if (newViewModel != null)
                {
                    newPage.DataContext = newViewModel;
                }
                else if ((newViewModel = newPage?.DataContext) != null)
                {
                    await ViewModelActionStrategy.NavigatingToAsync(newViewModel, mode, false, from, to, this);
                }

                // raise Navigated event
                Two.RaiseNavigated(new NavigatedEventArgs()
                {
                    Parameter      = parameter,
                    NavigationMode = mode,
                    PageType       = newPage?.GetType(),
                });

                // call fromViewModel.OnNavigatedFrom()
                await ViewModelActionStrategy.NavigatedFromAsync(fromViewModel, mode, false, from, to, this);

                // call toTemplate10ViewModel.Properties
                if (newViewModel is ITemplate10ViewModel vm)
                {
                    vm.NavigationService = this;
                }

                // call newViewModel.OnNavigatedToAsync()
                await ViewModelActionStrategy.NavigatedToAsync(newViewModel, mode, false, from, to, this);

                // finally, all-good
                return(true);
            }
            catch (Exception ex)
            {
                this.Log(ex.Message, Severities.Error);
                Debugger.Break();
                throw;
            }
            finally
            {
                _navigationOrchestratorAsyncSemaphore.Release();
            }
        }
예제 #2
0
        void INavigationService2.RaiseNavigatingCancels(object parameter, bool suspending, NavigationMode mode, NavigationInfo toInfo, out ContinueResult cancel)
        {
            var navigatingDeferral  = new Common.DeferralExManager();
            var navigatingEventArgs = new NavigatingEventArgs(navigatingDeferral)
            {
                Parameter           = parameter,
                Suspending          = suspending,
                NavigationMode      = mode,
                TargetPageType      = toInfo.PageType,
                TargetPageParameter = toInfo.Parameter,
            };

            Navigating?.Invoke(this, navigatingEventArgs);
            cancel = navigatingEventArgs.Cancel ? ContinueResult.Stop : ContinueResult.Continue;
        }