Exemple #1
0
        private async Task <bool> NavigationOrchestratorAsync(Type page, object parameter, NavigationMode mode, Func <bool> navigate)
        {
            using (var locker = await LockAsync.Create(navigationLock))
            {
                DebugWrite($"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 oldPage      = FrameFacadeInternal.Content as Page;
                var oldParameter = CurrentPageParam;
                var oldViewModel = oldPage?.DataContext;
                var oldPageState = await FrameFacadeInternal.GetPageStateAsync(oldPage?.GetType());

                var fromInfo = new NavigationInfo(oldPage?.GetType(), oldParameter, oldPageState);

                var toPageState = await FrameFacadeInternal.GetPageStateAsync(page?.GetType());

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

                // call oldViewModel.OnNavigatingFromAsync()
                var viewmodelCancels = await Settings.ViewModelActionStrategy.NavigatingFromAsync((oldViewModel, false), fromInfo, toInfo, this);

                if (viewmodelCancels)
                {
                    return(false);
                }

                // raise Navigating event
                RaiseNavigatingCancels(parameter, false, mode, toInfo, out var cancel);
                if (cancel)
                {
                    return(false);
                }

                // invoke navigate (however custom)
                if (navigate.Invoke())
                {
                    CurrentPageParam = parameter;
                    CurrentPageType  = page;
                }
                else
                {
                    return(false);
                }

                // fetch (current which is now new)
                var newPage      = FrameFacadeInternal.Content as Page;
                var newViewModel = newPage?.DataContext;

                // note: this has no value now, but it will
                await Settings.ViewModelActionStrategy.NavigatingToAsync((newViewModel, mode, false), fromInfo, toInfo, this);

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

                // call oldViewModel.OnNavigatedFrom()
                await Settings.ViewModelActionStrategy.NavigatedFromAsync((oldViewModel, false), fromInfo, toInfo, this);

                // call newViewModel.ResolveForPage()
                if (newViewModel == null)
                {
                    newViewModel        = ResolveViewModelForPage.Invoke(newPage);
                    newPage.DataContext = newViewModel;
                }

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

                // call newViewModel.OnNavigatedToAsync()
                await Settings.ViewModelActionStrategy.NavigatedToAsync((newViewModel, mode, false), fromInfo, toInfo, this);

                // finally
                return(true);
            }
        }
Exemple #2
0
        private async Task <bool> NavigationOrchestratorAsync(Type page, object parameter, NavigationMode mode, Func <bool> navigate)
        {
            if (!await navigationOrchestratorAsyncSemaphore.WaitAsync(TimeSpan.FromSeconds(10)))
            {
                throw new TimeoutException("Semaphore wait ellapsed");
            }

            // using (var locker = await LockAsync.Create(navigationLock))
            try
            {
                DebugWrite($"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 oldPage      = FrameFacadeInternal.Content as Page;
                var oldParameter = CurrentPageParam;
                var oldViewModel = oldPage?.DataContext;
                var oldPageState = await FrameFacadeInternal.GetPageStateAsync(oldPage?.GetType());

                var from = new NavigationInfo(oldPage?.GetType(), oldParameter, oldPageState);

                var newPageState = await FrameFacadeInternal.GetPageStateAsync(page?.GetType());

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

                // call oldViewModel.OnNavigatingFromAsync()
                var cancelled = await Settings.ViewModelActionStrategy.NavigatingFromAsync((oldViewModel, mode, false), from, to, this);

                if (cancelled)
                {
                    return(false);
                }

                // raise Navigating event
                RaiseNavigatingCancels(parameter, false, mode, to, out var cancel);
                if (cancel)
                {
                    return(false);
                }

                // try to resolve the view-model before navigation
                var newViewModel = default(object);
                switch (mode)
                {
                case NavigationMode.New:
                case NavigationMode.Refresh:
                    var strategy = Settings.ViewModelResolutionStrategy;
                    newViewModel = await strategy.ResolveViewModel(page);

                    if (newViewModel != null)
                    {
                        await Settings.ViewModelActionStrategy.NavigatingToAsync((newViewModel, mode, false), from, to, this);
                    }
                    break;
                }

                // navigate
                var newPage = default(Page);
                if (navigate.Invoke())
                {
                    if ((newPage = FrameFacadeInternal.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 Settings.ViewModelActionStrategy.NavigatingToAsync((newViewModel, mode, false), from, to, this);
                }

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

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

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

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

                // finally, all-good
                return(true);
            }
            catch (Exception ex)
            {
                throw;
            }
            finally
            {
                navigationOrchestratorAsyncSemaphore.Release();
            }
        }