コード例 #1
0
        internal async Task <bool> Navigate(Type viewModelType, object[] arguments, XamlNav.NavigationMode navigationMode, NavigationType navigationType)
        {
            if (!await this.CanChangePage(viewModelType, navigationMode, navigationType))
            {
                return(false);
            }

            FrameworkElement view      = null;
            IViewModel       viewModel = null;

            // Create a view
            if (navigationMode == XamlNav.NavigationMode.Back || navigationMode == XamlNav.NavigationMode.Forward || navigationMode == XamlNav.NavigationMode.New)
            {
                view = GetView(viewModelType);
            }

            // Create a view model
            if (navigationMode == XamlNav.NavigationMode.Back || navigationMode == XamlNav.NavigationMode.Forward || navigationMode == XamlNav.NavigationMode.Refresh)
            {
                viewModel = Factory.Create(viewModelType, arguments).As <IViewModel>(); // Use Factory create here so that the factory extensions are invoked
            }
            // Bind the IsLoading if implemented
            if (view != null)
            {
                view.SetBinding(Control.IsEnabledProperty, new Binding
                {
                    Path      = new PropertyPath(nameof(IViewModel.IsLoading)),
                    Converter = new BooleanInvertConverter()
                });
            }

            if (navigationMode == XamlNav.NavigationMode.Back || navigationMode == XamlNav.NavigationMode.Forward)
            {
                // Setup the page transition animations
                if (view.Transitions != null && view.Transitions.Count > 0)
                {
                    this.ContentTransitions = view.Transitions;
                }
                else
                {
                    this.ContentTransitions = this.DefaultChildrenTransitions;
                }

                // we need to keep our old datacontext to dispose them properly later on
                var oldDataContext = this.ContentDataContext;
                var oldView        = this.Content.As <FrameworkElement>();
                // Assign our new content
                this.Content = view;
                await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => view.DataContext = viewModel);

                // Invoke the Navigation stuff in the current datacontext
                await AsyncHelper.NullGuard(viewModel.As <INavigable>()?.OnNavigatedTo(new NavigationInfo(navigationMode, navigationType, oldDataContext?.GetType())));

                // Remove the reference of the old vm from the old view
                oldView.IsNotNull(x => x.DataContext = null);
                // Now invoke the navigated from on our old data context
                await AsyncHelper.NullGuard(oldDataContext?.As <INavigable>()?.OnNavigatedFrom(new NavigationInfo(navigationMode, navigationType, viewModelType)));

                // dispose the old viewmodel
                oldDataContext?.TryDispose();
            }
            else if (navigationMode == XamlNav.NavigationMode.New)
            {
                // NavigationMode.New means recreate the view but preserve the viewmodel
                // we need to keep our current datacontext for later reassigning
                var currentDataContext = this.ContentDataContext;
                var oldView            = this.Content.As <FrameworkElement>();

                // cancel this if the oldview and the new view are the same
                if (oldView.GetType() == view.GetType())
                {
                    return(false);
                }

                // Assign our content
                this.Content = view;
                await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => view.DataContext = currentDataContext);

                // Invoke the Navigation stuff in the current datacontext
                await AsyncHelper.NullGuard(currentDataContext.As <INavigable>()?.OnNavigatedTo(new NavigationInfo(navigationMode, navigationType, currentDataContext.GetType())));

                // Remove the reference of the current viewmodel from the old view
                oldView.IsNotNull(x => x.DataContext = null);
            }
            else if (navigationMode == XamlNav.NavigationMode.Refresh)
            {
                // we need to keep our old datacontext to dispose them properly later on
                var oldDataContext = this.ContentDataContext;
                // NavigationMode.Refresh means recreate the view model but preserve the view
                viewModel = Factory.Create(viewModelType, arguments).As <IViewModel>();
                await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => view.DataContext = viewModel);

                // Invoke the Navigation stuff in the current datacontext
                await AsyncHelper.NullGuard(viewModel.As <INavigable>()?.OnNavigatedTo(new NavigationInfo(navigationMode, navigationType, viewModelType)));

                // dispose the old viewmodel
                oldDataContext?.TryDispose();
            }

            // Refresh the stacks
            if (navigationMode == XamlNav.NavigationMode.Forward)
            {
                // we have to check if the current viewmodel is the same as the one the top of the forwardstack
                // if that is the case we remove it from the stack
                // if that is not the case, then we clear the stack
                if (this.ForwardStack.Count > 0)
                {
                    var stackEntry = this.ForwardStack[0];

                    // Remove the stack if equal
                    if (viewModelType == stackEntry.ViewModelType &&
                        ((stackEntry.Parameters != null && arguments != null && stackEntry.Parameters.SequenceEqual(arguments)) ||
                         (stackEntry.Parameters == null && arguments == null)))
                    {
                        this.ForwardStack.RemoveAt(0);
                    }
                    else
                    {
                        this.ForwardStack.Clear();
                    }
                }
            }

            if (navigationMode == XamlNav.NavigationMode.Back || navigationMode == XamlNav.NavigationMode.Forward)
            {
                this.BackStack.Add(new PageStackEntry(viewModelType, arguments));
            }

            // remove entries from stack
            if (this.MaxStackSize > 1)
            {
                if (this.BackStack.Count > this.MaxStackSize + 1)
                {
                    this.BackStack.RemoveAt(0);
                }

                if (this.ForwardStack.Count > this.MaxStackSize)
                {
                    this.ForwardStack.RemoveAt(this.ForwardStack.Count - 1);
                }
            }

            this.CanGoBack    = this.BackStack.Count > 1;
            this.CanGoForward = this.ForwardStack.Count > 0;

            this.Navigated?.Invoke(this, EventArgs.Empty);
            return(true);
        }
コード例 #2
0
 private async void OpenInfoAction(IViewModel arg) =>
 await this.Navigator.NavigateAsync <ItemInfoViewModel>(arg.As <TypeNameItemViewModel>().ItemId);