예제 #1
0
        private void OnSelectedItemChangedInternal(TViewModel oldValue, TViewModel newValue)
        {
            ISelectable selectable;
            bool        containsOld = false;

            if (ItemsSource.Contains(oldValue))
            {
                selectable = oldValue as ISelectable;
                if (selectable != null)
                {
                    selectable.IsSelected = false;
                }
                containsOld = true;
            }

            selectable = newValue as ISelectable;
            if (selectable != null)
            {
                selectable.IsSelected = true;
            }

            if (containsOld || newValue != null)
            {
                NavigationMode mode = newValue != null && newValue.Settings.Metadata.Remove(NavigationConstants.IsFirstNavigation) ? NavigationMode.New : NavigationMode.Refresh;
                NavigationDispatcher.OnNavigated(new NavigationContext(NavigationType.Tab, mode, containsOld ? oldValue : null, newValue, this));
            }
            OnSelectedItemChanged(oldValue, newValue);
            RaiseSelectedItemChanged(oldValue, newValue);
        }
예제 #2
0
        protected virtual UIViewController GetCurrentViewController()
        {
            bool isWindow  = true;
            var  viewModel = NavigationDispatcher.GetTopViewModel(NavigationType.Window);

            if (viewModel == null)
            {
                isWindow  = false;
                viewModel = NavigationDispatcher.GetTopViewModel(NavigationType.Page);
            }
            var controller = viewModel.GetCurrentView <object>() as UIViewController;

            if (controller == null)
            {
                return((UIViewController)ViewModel
                       .GetIocContainer(true)
                       .Get <INavigationService>()
                       .CurrentContent);
            }
            if (isWindow)
            {
                var weakThis = ServiceProvider.WeakReferenceFactory(this);
                viewModel.AddClosedHandler((sender, args) => ((ModalViewMediator)weakThis.Target)?.OnViewClosed(sender, args));
            }
            return(controller);
        }
예제 #3
0
        protected override void ShowView(IWindowView view, bool isDialog, IDataContext context)
        {
            var currentViewModel = context.GetData(NavigationConstants.ViewModel);
            var topViewModel     = NavigationDispatcher.GetOpenedViewModels(NavigationType.Window).LastOrDefault(vm => vm != currentViewModel);

            if (topViewModel != null)
            {
                view.Owner = topViewModel.Settings.Metadata.GetData(ViewModelConstants.View);
            }

            try
            {
                if (isDialog)
                {
                    view.ShowDialog();
                }
                else
                {
                    view.Show();
                }
            }
            catch
            {
                if (isDialog)
                {
                    view.Close();
                }
                throw;
            }
        }
예제 #4
0
        void IHandler <ForegroundNavigationMessage> .Handle(object sender, ForegroundNavigationMessage message)
        {
            var viewModel = Window?.RootViewController?.DataContext() as IViewModel;

            if (viewModel != null && viewModel.Settings.State.Contains(IsRootConstant))
            {
                NavigationDispatcher.OnNavigated(new NavigationContext(NavigationType.Page, NavigationMode.Foreground, null, viewModel, this, message.Context));
            }
        }
예제 #5
0
        protected virtual void InitializeRootPage(IViewModel viewModel, IDataContext context)
        {
            var mainPage       = (Page)ViewManager.GetOrCreateView(viewModel, true, context);
            var navigationPage = mainPage as NavigationPage;

            if (WrapToNavigationPage)
            {
                navigationPage = CreateNavigationPage(mainPage);
            }

            var isRoot = navigationPage == null || ReferenceEquals(mainPage, navigationPage);

            if (navigationPage != null)
            {
                INavigationService navigationService;
                if (!ServiceProvider.TryGet(out navigationService))
                {
                    navigationService = CreateNavigationService();
                    ServiceProvider.IocContainer.BindToConstant(navigationService);
                }

                //Activating navigation provider if need
                INavigationProvider provider;
                ServiceProvider.TryGet(out provider);

                navigationService.UpdateRootPage(navigationPage, viewModel);
                mainPage = navigationPage;
            }
            Application.Current.MainPage = mainPage;

            EventHandler <Page, CancelEventArgs> handler = OnBackButtonPressed;

            XamarinFormsToolkitExtensions.BackButtonPressed -= handler;

            var mode = NavigationMode.New;

            if (isRoot)
            {
                XamarinFormsToolkitExtensions.BackButtonPressed += handler;

                if (viewModel.Settings.State.Contains(IsRootConstant))
                {
                    mode = NavigationMode.Refresh;
                }
                else
                {
                    viewModel.Settings.State.AddOrUpdate(IsRootConstant, null);
                }
                viewModel.Settings.Metadata.AddOrUpdate(ViewModelConstants.CanCloseHandler, CanCloseRootViewModel);
                NavigationDispatcher.OnNavigated(new NavigationContext(NavigationType.Page, mode, null, viewModel, this, context));
            }
            else
            {
                mainPage.SetNavigationParameter(NavigationProvider.GenerateNavigationParameter(viewModel));
                ServiceProvider.Get <INavigationProvider>().Restore(context);
            }
        }
예제 #6
0
        void IHandler <ForegroundNavigationMessage> .Handle(object sender, ForegroundNavigationMessage message)
        {
            var viewModel = Application.Current?.MainPage?.BindingContext as IViewModel;

            if (viewModel != null && viewModel.Settings.State.Contains(IsRootConstant))
            {
                NavigationDispatcher.OnNavigated(new NavigationContext(NavigationType.Page, NavigationMode.Foreground, null, viewModel, this, message.Context));
            }
        }
예제 #7
0
        private void OnViewModelsChanged(IList newItems, IList oldItems, int oldStartingIndex)
        {
            if (newItems != null && newItems.Count != 0)
            {
                for (int index = 0; index < newItems.Count; index++)
                {
                    var viewModel = (TViewModel)newItems[index];
                    // ReSharper disable once NotResolvedInText
                    Should.NotBeNull(viewModel, "newItem");
                    var selectable = viewModel as ISelectable;
                    if (selectable != null)
                    {
                        selectable.PropertyChanged += _propertyChangedWeakEventHandler;
                    }
                    viewModel.Settings.Metadata.AddOrUpdate(NavigationConstants.IsFirstNavigation, null);
                    OnViewModelAdded(viewModel);
                    RaiseViewModelAdded(viewModel);
                }
            }

            if (oldItems != null && oldItems.Count != 0)
            {
                for (int index = 0; index < oldItems.Count; index++)
                {
                    var viewModel = (TViewModel)oldItems[index];
                    if (SelectedItem == null || ReferenceEquals(SelectedItem, viewModel))
                    {
                        TryUpdateSelectedValue(oldStartingIndex + index);
                    }

                    var selectable = viewModel as ISelectable;
                    if (selectable != null)
                    {
                        selectable.PropertyChanged -= _propertyChangedWeakEventHandler;
                        if (selectable.IsSelected)
                        {
                            selectable.IsSelected = false;
                        }
                    }
                    INavigationContext context = _lastRemoveContext;
                    _lastRemoveContext = null;
                    if (context == null || context.ViewModelFrom != viewModel)
                    {
                        context = new NavigationContext(NavigationType.Tab, NavigationMode.Remove, viewModel, null, this);
                    }
                    viewModel.Settings.Metadata.Remove(NavigationConstants.IsFirstNavigation);
                    NavigationDispatcher.OnNavigated(context);
                    OnViewModelRemoved(viewModel);
                    RaiseViewModelRemoved(viewModel);
                    if (DisposeViewModelOnRemove)
                    {
                        viewModel.Dispose();
                    }
                }
            }
        }
예제 #8
0
        protected virtual void OnApplicationStart()
        {
            var openedViewModels = NavigationDispatcher.GetOpenedViewModels(NavigationType.Page);

            foreach (var openedViewModel in openedViewModels)
            {
                Tracer.Warn($"There is an open view model {openedViewModel} after app restart");
                NavigationDispatcher.OnNavigated(new NavigationContext(NavigationType.Page, NavigationMode.Remove, openedViewModel.ViewModel, null, this));
            }
        }
        protected virtual void OnNavigated(INavigationContext context)
        {
            var vmFrom = context.ViewModelFrom;
            var vmTo   = context.ViewModelTo;
            var mode   = context.NavigationMode;

            //only this mode allows to renavigate.
            if (ReferenceEquals(vmFrom, vmTo) && mode != NavigationMode.Refresh && mode != NavigationMode.Undefined)
            {
                if (vmFrom != null)
                {
                    Tracer.Error("Possible bug in navigation, navigate to the same view model with mode " + mode);
                }
                return;
            }
            if (mode != NavigationMode.Remove && mode != NavigationMode.Background && mode != NavigationMode.Foreground)
            {
                CurrentViewModel = vmTo;
                if (vmTo != null)
                {
                    if (!vmTo.Settings.State.Contains(IsNavigatedConstant))
                    {
                        vmTo.Settings.State.AddOrUpdate(IsNavigatedConstant, null);
                    }
                    if (!vmTo.Settings.Metadata.Contains(ViewModelConstants.CanCloseHandler))
                    {
                        vmTo.Settings.Metadata.AddOrUpdate(ViewModelConstants.CanCloseHandler, CanCloseViewModel);
                    }
                    vmTo.InvalidateCommands();
                }
            }

            NavigationDispatcher.OnNavigated(context);
            if (context.NavigationMode.IsClose())
            {
                if (vmFrom != null)
                {
                    vmFrom.Settings.State.Remove(IsNavigatedConstant);
                    vmFrom.Settings.Metadata.Remove(ViewModelConstants.CanCloseHandler);
#if WINDOWS_UWP
                    lock (_openedViewModels)
                        _openedViewModels.Remove(vmFrom.GetViewModelId());
#endif
                }
            }
            else if (vmTo != null)
            {
#if WINDOWS_UWP
                lock (_openedViewModels)
                    _openedViewModels[vmTo.GetViewModelId()] = vmTo;
#endif
            }
        }
        protected virtual INavigationContext CreateContextNavigateFrom(NavigatingCancelEventArgsBase args)
        {
            IViewModel viewModelFrom = null, viewModelTo = null;

            if (args.NavigationMode.IsClose())
            {
                viewModelFrom = args.Context.GetData(NavigationConstants.ViewModel);
            }
            else
            {
                viewModelTo = args.Context.GetData(NavigationConstants.ViewModel);
            }

            if (args.NavigationMode == NavigationMode.Remove)
            {
                if (viewModelFrom != null)
                {
                    return(new NavigationContext(NavigationType.Page, NavigationMode.Remove, viewModelFrom, null, this, args.Context));
                }
                Tracer.Error("Possible bug in navigation, navigate with Remove mode without ViewModel");
                return(null);
            }

            if (viewModelFrom == null)
            {
                viewModelFrom = CurrentViewModel;
            }
            if (viewModelFrom == null)
            {
                return(null);
            }

            Guid viewModelId;

            if (viewModelTo == null && GetViewModelTypeFromParameter(args.Parameter, out viewModelId) != null)
            {
                viewModelTo = ViewModelProvider.TryGetViewModelById(viewModelId);
            }

            bool doNotTrackViewModelTo = false;

            if (viewModelTo == null && args.NavigationMode == NavigationMode.Back)
            {
                viewModelTo = NavigationDispatcher.GetPreviousOpenedViewModelOrParent(viewModelFrom, NavigationType.Page, out doNotTrackViewModelTo, this);
            }
            return(new NavigationContext(NavigationType.Page, args.NavigationMode, viewModelFrom, viewModelTo, this, args.Context)
            {
                { NavigationConstants.DoNotTrackViewModelTo, doNotTrackViewModelTo }
            });
        }
 private void Renavigate([NotNull] INavigationContext context, NavigatingCancelEventArgsBase args)
 {
     if (_navigatingCancelArgs == null)
     {
         if (!NavigationService.Navigate(args))
         {
             TryCompleteNavigationTask(args.Context, false);
             NavigationDispatcher.OnNavigationCanceled(context);
         }
     }
     else
     {
         _navigatingCancelArgs.Cancel = false;
     }
 }
        protected virtual void OnNavigating(NavigatingCancelEventArgsBase args)
        {
            if (args.Context.Contains(IgnoreNavigatingConstant))
            {
                return;
            }
            var context = CreateContextNavigateFrom(args);

            if (context == null)
            {
                return;
            }

            args.Cancel = true;
            var navigateTask = !args.IsCancelable
                ? Empty.TrueTask
                : NavigationDispatcher.OnNavigatingAsync(context);

            navigateTask.TryExecuteSynchronously(task =>
            {
                if (!task.IsCanceled && task.IsFaulted)
                {
                    TryCompleteNavigationTask(args.Context, false);
                    NavigationDispatcher.OnNavigationFailed(context, task.Exception);
                    return;
                }

                if (task.IsCanceled || !task.Result)
                {
                    TryCompleteNavigationTask(args.Context, false);
                    if (!context.NavigationMode.IsClose())
                    {
                        NavigationDispatcher.OnNavigationCanceled(context);
                    }
                    return;
                }
                ThreadManager.Invoke(ExecutionMode.AsynchronousOnUiThread, this, context, args, (@this, ctx, e) =>
                {
                    e.Context.AddOrUpdate(IgnoreNavigatingConstant, null);
                    @this.Renavigate(ctx, e);
                });
            });
        }
예제 #13
0
        public virtual bool Restore(IDataContext context, IViewModelPresenter parentPresenter)
        {
            _initialized = true;

            var viewModel = context.GetData(NavigationConstants.ViewModel);

            if (viewModel == null)
            {
                return(false);
            }

            if (viewModel.Settings.State.Contains(IsRootConstant))
            {
                viewModel.Settings.Metadata.AddOrUpdate(ViewModelConstants.CanCloseHandler, (model, o) => false);
                NavigationDispatcher.OnNavigated(new NavigationContext(NavigationType.Page, NavigationMode.Refresh, null, viewModel, this, context));
                return(true);
            }
            return(false);
        }
예제 #14
0
        private Task <bool> TryCloseRootAsync(IViewModel viewModel, IDataContext context)
        {
            if (viewModel == null || !viewModel.Settings.State.Contains(IsRootConstant) || viewModel.Settings.Metadata.Contains(IsClosed))
            {
                return(null);
            }

            var currentView = viewModel.GetCurrentView <object>();

            var backButtonAction = XamarinFormsToolkitExtensions.SendBackButtonPressed?.Invoke(currentView);

            if (backButtonAction == null)
            {
                return(null);
            }

            var navigationContext = new NavigationContext(NavigationType.Page, NavigationMode.Back, viewModel, null, this, context);
            var task = NavigationDispatcher.OnNavigatingAsync(navigationContext);

            if (task.IsCompleted)
            {
                if (task.Result)
                {
                    viewModel.Settings.Metadata.AddOrUpdate(IsClosed, null);
                    _hasRootPage = false;
                    NavigationDispatcher.OnNavigated(navigationContext);
                }
                return(task);
            }
            return(task.TryExecuteSynchronously(t =>
            {
                if (!t.Result)
                {
                    return false;
                }
                _hasRootPage = false;
                viewModel.Settings.Metadata.AddOrUpdate(IsClosed, null);
                backButtonAction();
                NavigationDispatcher.OnNavigated(navigationContext);
                return true;
            }));
        }
예제 #15
0
        private Task <bool> CloseViewModel(INavigationDispatcher navigationDispatcher, IViewModel viewModel, IDataContext ctx)
        {
            if (!(viewModel is TViewModel))
            {
                return(Empty.FalseTask);
            }
            var removeCtx = new NavigationContext(NavigationType.Tab, NavigationMode.Remove, viewModel, null, this, ctx);

            return(NavigationDispatcher
                   .OnNavigatingAsync(removeCtx)
                   .TryExecuteSynchronously(task =>
            {
                if (task.Result)
                {
                    _lastRemoveContext = removeCtx;
                    return ItemsSource.Remove((TViewModel)viewModel);
                }
                return false;
            }));
        }
예제 #16
0
 internal override void OnDisposeInternal(bool disposing)
 {
     if (disposing)
     {
         if (ItemsSource.Count != 0)
         {
             var viewModels = ItemsSource.ToArray();
             for (int i = 0; i < viewModels.Length; i++)
             {
                 NavigationDispatcher.OnNavigated(new NavigationContext(NavigationType.Tab, NavigationMode.Remove, viewModels[i], null, this));
             }
         }
         SelectedItemChanged            = null;
         _selectedItemChangedNonGeneric = null;
         ViewModelAdded              = null;
         ViewModelRemoved            = null;
         _viewModelAddedNonGeneric   = null;
         _viewModelRemovedNonGeneric = null;
     }
     base.OnDisposeInternal(disposing);
 }
예제 #17
0
 protected virtual void InitializeRootView(IViewModel viewModel, IDataContext context)
 {
     Window.RootViewController = (UIViewController)ViewManager.GetOrCreateView(viewModel, null, context);
     NavigationDispatcher.OnNavigated(new NavigationContext(NavigationType.Page, NavigationMode.New, null, viewModel, this, context));
 }