Ejemplo n.º 1
0
        public async Task SaveNavigationAsync()
        {
            DebugWrite($"Frame: {FrameFacadeInternal.FrameId}");

            if (CurrentPageType == null)
            {
                return;
            }
            var args = new CancelEventArgs <Type>(FrameFacadeInternal.CurrentPageType);

            BeforeSavingNavigation?.Invoke(this, args);
            if (args.Cancel)
            {
                return;
            }

            var state = FrameFacadeInternal.PageStateSettingsService(GetType().ToString());

            if (state == null)
            {
                throw new InvalidOperationException("State container is unexpectedly null");
            }

            state.Write <string>("CurrentPageType", CurrentPageType.AssemblyQualifiedName);
            state.Write <object>("CurrentPageParam", CurrentPageParam);
            state.Write <string>("NavigateState", FrameFacadeInternal?.GetNavigationState());
            await Task.CompletedTask;
        }
Ejemplo n.º 2
0
 public void GoBack(NavigationTransitionInfo infoOverride = null)
 {
     if (FrameFacadeInternal.CanGoBack)
     {
         FrameFacadeInternal.GoBack(infoOverride);
     }
 }
Ejemplo n.º 3
0
        public async void Resuming()
        {
            DebugWrite($"Frame: {FrameFacadeInternal.FrameId}");

            var page = FrameFacadeInternal.Content as Page;

            if (page != null)
            {
                var dataContext = ResolveForPage(page);
                if (dataContext != null)
                {
                    dataContext.NavigationService = this;
                    dataContext.Dispatcher        = this.GetDispatcherWrapper();
                    dataContext.SessionState      = BootStrapper.Current.SessionState;
                    var pageState = FrameFacadeInternal.PageStateSettingsService(page.GetType(), parameter: FrameFacadeInternal.CurrentPageParam).Values;
                    await dataContext.OnNavigatedToAsync(FrameFacadeInternal.CurrentPageParam, NavigationMode.Refresh, pageState);

                    // update bindings after NavTo initializes data
                    //XamlUtils.InitializeBindings(page);
                    if (page.Content is UserControl pageWith)
                    {
                        XamlUtils.UpdateBindings(pageWith);
                    }
                    else
                    {
                        XamlUtils.UpdateBindings(page);
                    }
                }
            }
        }
Ejemplo n.º 4
0
        async Task NavigateToAsync(NavigationMode mode, object parameter, object frameContent = null)
        {
            DebugWrite($"Mode: {mode}, Parameter: {parameter} FrameContent: {frameContent}");

            frameContent = frameContent ?? FrameFacadeInternal.Frame.Content;

            LastNavigationParameter = parameter;
            LastNavigationType      = frameContent.GetType().FullName;

            var page = frameContent as Page;

            if (page != null)
            {
                if (mode == NavigationMode.New)
                {
                    var pageState = FrameFacadeInternal.PageStateSettingsService(page.GetType()).Values;
                    pageState?.Clear();
                }

                var dataContext = ResolveForPage(page);
                if (dataContext != null)
                {
                    // prepare for state load
                    dataContext.NavigationService = this;
                    dataContext.Dispatcher        = this.GetDispatcherWrapper();
                    dataContext.SessionState      = BootStrapper.Current.SessionState;
                    var pageState = FrameFacadeInternal.PageStateSettingsService(page.GetType()).Values;
                    await dataContext.OnNavigatedToAsync(parameter, mode, pageState);

                    // update bindings after NavTo initializes data
                    XamlUtils.InitializeBindings(page);
                    XamlUtils.UpdateBindings(page);
                }
            }
        }
Ejemplo n.º 5
0
        public async Task SaveAsync()
        {
            // save navigation state into settings

            DebugWrite($"Frame: {FrameFacade.FrameId}");

            if (CurrentPageType == null)
            {
                return;
            }
            if (RaiseBeforeSavingNavigation())
            {
                return;
            }

            var frameState = Suspension.GetFrameState();

            if (frameState == null)
            {
                throw new InvalidOperationException("State container is unexpectedly null");
            }

            frameState.Write <string>("CurrentPageType", CurrentPageType.AssemblyQualifiedName);
            frameState.Write <object>("CurrentPageParam", CurrentPageParam);
            frameState.Write <string>("NavigateState", FrameFacadeInternal.GetNavigationState());

            await Task.CompletedTask;
        }
Ejemplo n.º 6
0
        public async Task <bool> NavigateAsync(Type page, object parameter = null, NavigationTransitionInfo infoOverride = null)
        {
            DebugWrite($"Page: {page}, Parameter: {parameter}, NavigationTransitionInfo: {infoOverride}");

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

            // use CurrentPageType/Param instead of LastNavigationType/Parameter to avoid new navigation to the current
            // page in some race conditions.
            if ((page.FullName == CurrentPageType?.FullName) && (parameter == CurrentPageParam))
            {
                return(false);
            }

            if ((page.FullName == CurrentPageType?.FullName) && (parameter?.Equals(CurrentPageParam) ?? false))
            {
                return(false);
            }


            parameter = SerializationService.Serialize(parameter);

            await Task.CompletedTask;

            return(FrameFacadeInternal.Navigate(page, parameter, infoOverride));
        }
Ejemplo n.º 7
0
        public async Task <bool> RestoreSavedNavigationAsync()
        {
            DebugWrite($"Frame: {FrameFacadeInternal.FrameId}");

            try
            {
                var state = FrameFacadeInternal.PageStateSettingsService(GetType().ToString());
                if (state == null || !state.Exists("CurrentPageType"))
                {
                    return(false);
                }

                FrameFacadeInternal.CurrentPageType  = Type.GetType(state.Read <string>("CurrentPageType"));
                FrameFacadeInternal.CurrentPageParam = state.Read <object>("CurrentPageParam");
                FrameFacadeInternal.SetNavigationState(state.Read <string>("NavigateState"));

                await NavigateToAsync(NavigationMode.Refresh, FrameFacadeInternal.CurrentPageParam);

                while (FrameFacadeInternal.Frame.Content == null)
                {
                    Task.Yield().GetAwaiter().GetResult();
                }
                AfterRestoreSavedNavigation?.Invoke(this, FrameFacadeInternal.CurrentPageType);
                return(true);
            }
            catch { return(false); }
        }
Ejemplo n.º 8
0
        public async Task <bool> NavigateAsync(Type page, object parameter = null, NavigationTransitionInfo infoOverride = null)
        {
            DebugWrite($"Page: {page}, Parameter: {parameter}, NavigationTransitionInfo: {infoOverride}");

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

            if ((page.FullName == LastNavigationType) && (parameter == LastNavigationParameter))
            {
                return(false);
            }

            if ((page.FullName == LastNavigationType) && (parameter?.Equals(LastNavigationParameter) ?? false))
            {
                return(false);
            }

            parameter = SerializationService.Serialize(parameter);

            await Task.CompletedTask;

            return(FrameFacadeInternal.Navigate(page, parameter, infoOverride));
        }
Ejemplo n.º 9
0
        /*
         *  Navigate<T> allows developers to navigate using a
         *  page key instead of the view type. This is accomplished by
         *  creating a custom Enum and setting up the PageKeys dict
         *  with the Key/Type pairs for your views. The dict is
         *  shared by all NavigationServices and is stored in
         *  the BootStrapper (or Application) of the app.
         *
         *  Implementation example:
         *
         *  // define your Enum
         *  public Enum Pages { MainPage, DetailPage }
         *
         *  // setup the keys dict
         *  var keys = BootStrapper.PageKeys<Views>();
         *  keys.Add(Pages.MainPage, typeof(Views.MainPage));
         *  keys.Add(Pages.DetailPage, typeof(Views.DetailPage));
         *
         *  // use Navigate<T>()
         *  NavigationService.Navigate(Pages.MainPage);
         */

        // T must be the same custom Enum used with BootStrapper.PageKeys()
        public bool Navigate <T>(T key, object parameter = null, NavigationTransitionInfo infoOverride = null)
            where T : struct, IConvertible
        {
            DebugWrite($"Key: {key}, Parameter: {parameter}, NavigationTransitionInfo: {infoOverride}");

            var keys = BootStrapper.Current.PageKeys <T>();

            if (!keys.ContainsKey(key))
            {
                throw new KeyNotFoundException(key.ToString());
            }

            var page = keys[key];

            if (page.FullName.Equals(LastNavigationType))
            {
                if (parameter == LastNavigationParameter)
                {
                    return(false);
                }

                if (parameter != null && parameter.Equals(LastNavigationParameter))
                {
                    return(false);
                }
            }

            parameter = SerializationService.Serialize(parameter);
            return(FrameFacadeInternal.Navigate(page, parameter, infoOverride));
        }
Ejemplo n.º 10
0
 public void GoBack()
 {
     if (FrameFacadeInternal.CanGoBack)
     {
         FrameFacadeInternal.GoBack();
     }
 }
Ejemplo n.º 11
0
        public async Task <bool> LoadAsync()
        {
            DebugWrite($"Frame: {FrameFacadeInternal.FrameId}");

            try
            {
                var index = WindowWrapper.Current().NavigationServices.IndexOf(this);
                var state = FrameFacadeInternal.PageStateSettingsService($"NavigationService{index}");
                if (state == null || !state.Exists("CurrentPageType"))
                {
                    return(false);
                }

                FrameFacadeInternal.CurrentPageType  = Type.GetType(state.Read <string>("CurrentPageType"));
                FrameFacadeInternal.CurrentPageParam = state.Read <object>("CurrentPageParam");
                FrameFacadeInternal.NavigationService.NavigationState = state.Read <string>("NavigateState");

                await NavigateToAsync(NavigationMode.Refresh, FrameFacadeInternal.CurrentPageParam);

                while (FrameFacadeInternal.Frame.Content == null)
                {
                    await Task.Delay(1);
                }
                AfterRestoreSavedNavigation?.Invoke(this, FrameFacadeInternal.CurrentPageType);
                return(true);
            }
            catch { return(false); }
        }
Ejemplo n.º 12
0
 public async Task <bool> RefreshAsync()
 {
     return(await NavigationOrchestratorAsync(CurrentPageType, CurrentPageParam, NavigationMode.Refresh, () =>
     {
         Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().Reset();
         FrameFacadeInternal.SetNavigationState(FrameFacadeInternal.GetNavigationState());
         return true;
     }));
 }
Ejemplo n.º 13
0
        // after navigate
        async Task NavigateFromAsync(Page page, INavigable dataContext, bool suspending)
        {
            DebugWrite($"Suspending: {suspending}");

            dataContext.NavigationService = this;
            dataContext.Dispatcher        = this.GetDispatcherWrapper();
            dataContext.SessionState      = BootStrapper.Current.SessionState;

            var pageState = FrameFacadeInternal.PageStateSettingsService(page.GetType()).Values;
            await dataContext.OnNavigatedFromAsync(pageState, suspending);
        }
Ejemplo n.º 14
0
        // after navigate
        async Task NavigateFromAsync(Page page, INavigable dataContext, bool suspending)
        {
            DebugWrite($"Suspending: {suspending}");

            dataContext.NavigationService = this;
            dataContext.Dispatcher        = this.GetDispatcherWrapper();
            dataContext.SessionState      = BootStrapper.Current.SessionState;

            var index     = WindowWrapper.Current().NavigationServices.IndexOf(this);
            var pageState = FrameFacadeInternal.PageStateSettingsService($"NavigationService{index}").Values;
            await dataContext.OnNavigatedFromAsync(pageState, suspending).ConfigureAwait(false);
        }
Ejemplo n.º 15
0
        public async Task <bool> NavigateAsync(Type page, object parameter = null, IDictionary <string, object> state = null, NavigationTransitionInfo infoOverride = null)
        {
            DebugWrite($"Page: {page}, Parameter: {parameter}, NavigationTransitionInfo: {infoOverride}");

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

            // use CurrentPageType/Param instead of LastNavigationType/Parameter to avoid new navigation to the current
            // page in some race conditions.
            if ((page.FullName == CurrentPageType?.FullName) && (parameter == CurrentPageParam))
            {
                return(false);
            }

            if ((page.FullName == CurrentPageType?.FullName) && (parameter?.Equals(CurrentPageParam) ?? false))
            {
                return(false);
            }

            if (state != null)
            {
                var pageState = FrameFacadeInternal.PageStateSettingsService(page, 1, parameter).Values;
                foreach (var item in state)
                {
                    pageState[item.Key] = item.Value;
                }
            }

            //var frameContent = FrameFacadeInternal.Frame.Content;
            //if (frameContent is Page current && frameContent is IDisposable disposable && page.FullName == CurrentPageType?.FullName)
            //{
            //    if (current.DataContext is INavigable dataContext)
            //    {
            //        await NavigatingFromAsync(current, page, parameter, dataContext, false, NavigationMode.Refresh);
            //        await NavigateFromAsync(current, dataContext, false);
            //    }

            //    await NavigateToAsync(NavigationMode.Refresh, parameter, current);

            //    FrameFacade.CurrentPageParam = parameter;
            //    FrameFacade.Frame.BackStack.Add(new PageStackEntry(page, SerializationService.Serialize(CurrentPageParam), infoOverride));
            //    return true;
            //}

            parameter = SerializationService.Serialize(parameter);

            return(FrameFacadeInternal.Navigate(page, parameter, infoOverride));
        }
Ejemplo n.º 16
0
        public async Task <bool> GoForwardAsync()
        {
            if (!FrameFacade.CanGoForward)
            {
                return(false);
            }
            var next      = FrameFacade.ForwardStack.FirstOrDefault();
            var parameter = SerializationService.Deserialize(next.Parameter?.ToString());

            return(await NavigationOrchestratorAsync(next.SourcePageType, parameter, NavigationMode.Forward, () =>
            {
                FrameFacadeInternal.GoForward();
                return true;
            }));
        }
Ejemplo n.º 17
0
        public async Task <bool> GoBackAsync(NavigationTransitionInfo infoOverride = null)
        {
            if (!CanGoBack)
            {
                return(false);
            }
            var previous  = FrameFacade.BackStack.LastOrDefault();
            var parameter = SerializationService.Deserialize(previous.Parameter?.ToString());

            return(await NavigationOrchestratorAsync(previous.SourcePageType, parameter, NavigationMode.Back, () =>
            {
                FrameFacadeInternal.GoBack(infoOverride);
                return true;
            }));
        }
Ejemplo n.º 18
0
        async Task NavigateToAsync(NavigationMode mode, object parameter, object frameContent = null)
        {
            DebugWrite($"Mode: {mode}, Parameter: {parameter} FrameContent: {frameContent}");

            frameContent = frameContent ?? FrameFacadeInternal.Frame.Content;

            LastNavigationParameter = parameter;
            LastNavigationType      = frameContent.GetType().FullName;

            var page = frameContent as Page;

            if (page != null)
            {
                if (mode == NavigationMode.New)
                {
                    var pageState = FrameFacadeInternal.PageStateSettingsService(page.GetType()).Values;
                    pageState?.Clear();
                }

                if (!(page.DataContext is INavigable) | page.DataContext == null)
                {
                    // to support dependency injection, but keeping it optional.
                    var viewmodel = BootStrapper.Current.ResolveForPage(page.GetType(), this);
                    if (viewmodel != null)
                    {
                        page.DataContext = viewmodel;
                    }
                }

                // call viewmodel
                var dataContext = page.DataContext as INavigable;
                if (dataContext != null)
                {
                    // prepare for state load
                    dataContext.NavigationService = this;
                    dataContext.Dispatcher        = WindowWrapper.Current(this)?.Dispatcher;
                    dataContext.SessionState      = BootStrapper.Current.SessionState;
                    var pageState = FrameFacadeInternal.PageStateSettingsService(page.GetType()).Values;
                    await dataContext.OnNavigatedToAsync(parameter, mode, pageState);

                    {
                        // update bindings after NavTo initializes data
                        XamlUtils.InitializeBindings(page);
                        XamlUtils.UpdateBindings(page);
                    }
                }
            }
        }
Ejemplo n.º 19
0
        public async Task <bool> LoadAsync()
        {
            // load navigation state from settings

            DebugWrite($"Frame: {FrameFacade.FrameId}");

            try
            {
                var frameState = Suspension.GetFrameState();
                if (frameState == null || !frameState.Exists("CurrentPageType"))
                {
                    return(false);
                }

                CurrentPageType  = frameState.Read <Type>("CurrentPageType");
                CurrentPageParam = frameState.Read <object>("CurrentPageParam");
                FrameFacadeInternal.SetNavigationState(frameState.Read <string>("NavigateState"));

                while (FrameFacade.Content == null)
                {
                    await Task.Delay(1);
                }

                var newPage      = FrameFacade.Content as Page;
                var newViewModel = newPage?.DataContext;

                if (newPage?.GetType() != CurrentPageType)
                {
                    // failed to load
                    return(false);
                }

                // newTemplate10ViewModel.Properties
                if (newViewModel is INavigable)
                {
                    Navigation.SetupViewModel(this, newViewModel as INavigable);
                }

                // newNavigatedAwareAsync.OnNavigatedTo
                await Navigation.NavedToAsync(newPage?.DataContext, NavigationMode.New, null, null, null, newPage, CurrentPageType, CurrentPageParam);

                RaiseAfterRestoreSavedNavigation();
                return(true);
            }
            catch { return(false); }
        }
Ejemplo n.º 20
0
        async Task NavigateToAsync(NavigationMode mode, object parameter, object frameContent = null)
        {
            DebugWrite($"Mode: {mode}, Parameter: {parameter} FrameContent: {frameContent}");

            frameContent = frameContent ?? FrameFacadeInternal.Frame.Content;

            var page = frameContent as Page;

            if (page != null)
            {
                if (page is IDisposable cleanup)
                {
                    cleanup.Dispose();
                }

                //if (mode == NavigationMode.New)
                //{
                //    var pageState = FrameFacadeInternal.PageStateSettingsService(page.GetType()).Values;
                //    pageState?.Clear();
                //}

                var dataContext = ResolveForPage(page);
                if (dataContext != null)
                {
                    // prepare for state load
                    dataContext.NavigationService = this;
                    dataContext.Dispatcher        = this.GetDispatcherWrapper();
                    dataContext.SessionState      = BootStrapper.Current.SessionState;
                    var pageState = FrameFacadeInternal.PageStateSettingsService(page.GetType(), parameter: parameter).Values;
                    await dataContext.OnNavigatedToAsync(parameter, mode, pageState);

                    // update bindings after NavTo initializes data
                    //XamlUtils.InitializeBindings(page);
                    if (page.Content is UserControl pageWith)
                    {
                        XamlUtils.UpdateBindings(pageWith);
                    }
                    else
                    {
                        XamlUtils.UpdateBindings(page);
                    }
                }
            }
        }
Ejemplo n.º 21
0
        // after navigate
        async Task NavigateFromAsync(bool suspending)
        {
            DebugWrite($"Suspending: {suspending}");

            var page = FrameFacadeInternal.Content as Page;

            if (page != null)
            {
                // call viewmodel
                var dataContext = ResolveForPage(page);
                if (dataContext != null)
                {
                    dataContext.NavigationService = this;
                    dataContext.Dispatcher        = this.GetDispatcherWrapper();
                    dataContext.SessionState      = BootStrapper.Current.SessionState;
                    var pageState = FrameFacadeInternal.PageStateSettingsService(page.GetType()).Values;
                    await dataContext.OnNavigatedFromAsync(pageState, suspending);
                }
            }
        }
Ejemplo n.º 22
0
        public async Task <bool> NavigateAsync(Type page, object parameter = null, NavigationTransitionInfo infoOverride = null)
        {
            DebugWrite($"Page: {page}, Parameter: {parameter}, NavigationTransitionInfo: {infoOverride}");

            // serialize parameter
            var serializedParameter = default(string);

            try
            {
                serializedParameter = Settings.SerializationStrategy.Serialize(parameter);
            }
            catch
            {
                throw new Exception("Parameter cannot be serialized. See https://github.com/Windows-XAML/Template10/wiki/Page-Parameters");
            }

            return(await NavigationOrchestratorAsync(page, parameter, NavigationMode.New, () =>
            {
                return FrameFacadeInternal.Navigate(page, serializedParameter, infoOverride);
            }));
        }
Ejemplo n.º 23
0
        public bool Navigate(Type page, object parameter = null, NavigationTransitionInfo infoOverride = null)
        {
            DebugWrite($"Page: {page}, Parameter: {parameter}, NavigationTransitionInfo: {infoOverride}");

            if (page == null)
            {
                throw new ArgumentNullException(nameof(page));
            }
            if (page.FullName.Equals(LastNavigationType))
            {
                if (parameter == LastNavigationParameter)
                {
                    return(false);
                }

                if (parameter != null && parameter.Equals(LastNavigationParameter))
                {
                    return(false);
                }
            }

            parameter = SerializationService.Serialize(parameter);
            return(FrameFacadeInternal.Navigate(page, parameter, infoOverride));
        }
Ejemplo n.º 24
0
 public void GoForward()
 {
     FrameFacadeInternal.GoForward();
 }
Ejemplo n.º 25
0
 public void Refresh(object param)
 {
     FrameFacadeInternal.Refresh(param);
 }
Ejemplo n.º 26
0
 public void Refresh()
 {
     FrameFacadeInternal.Refresh();
 }
Ejemplo n.º 27
0
 public void RaiseNavigating(NavigatingEventArgs e)
 {
     Navigating?.Invoke(this, e);
     // for backwards compat
     FrameFacadeInternal.RaiseNavigating(e);
 }
Ejemplo n.º 28
0
 public void RaiseForwardRequested(HandledEventArgs args)
 {
     ForwardRequested?.Invoke(this, args);
     // for backwards compat
     FrameFacadeInternal.RaiseForwardRequested(args);
 }
Ejemplo n.º 29
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);
            }
        }
Ejemplo n.º 30
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();
            }
        }