/// <summary> /// Create the navigation structure containing all ViewModels /// </summary> /// <param name="mainViewModels">An array of the application's ViewModels</param> private void LoadNavigation(ViewModelFoundation[] mainViewModels) { // Browse every ViewModels and search if it has a Navig attribute foreach(var vm in mainViewModels) { foreach(NavigAttribute na in vm.GetType().GetCustomAttributes(typeof(NavigAttribute), inherit: false)) { NavigConfig mainConf; // Check if it already exists a NavigConf with the same name var existingMainConf = navStructure.SingleOrDefault(n => n.Name == na.MainConfig.Name); if(existingMainConf != null) // If it's the case, set mainConf to it mainConf = existingMainConf; else { // Else we use the MainConfig as a new elem of navStructure if(!vm.IsAuthorized(CurrentUser)) na.MainConfig.Enabled = false; mainConf = na.MainConfig; navStructure.Add(mainConf); } // Assign the VM to the SubConfig or the main (if NavigAttribute has a single param) if(na.SubConfig != null) { if(!vm.IsAuthorized(CurrentUser)) na.SubConfig.Enabled = false; na.SubConfig.VM = vm; mainConf.SubConfig.Add(na.SubConfig); } else mainConf.VM = vm; } } CurrentMainNav = MainNavig[0]; CurrentViewModel = SubNavig[0].VM; CurrentMainNav.IsSelected = true; SubNavig[0].IsSelected = true; }
/// <summary> /// Instanciate the ApplicationViewModel. All registred ViewModels are injected into the param mainViewModels /// </summary> /// <param name="mainViewModels">An array of the application's ViewModels (injected)</param> /// <param name="loadingVm">The ViewModel representing the loading (injected)</param> /// <param name="authVm">The ViewModel representing the authentication (injected)</param> /// <param name="navConfs">An array containing the navigation configuration (injected)</param> public ApplicationViewModel(ViewModelFoundation[] mainViewModels, ViewModelFoundation loadingVm, ViewModelFoundation authVm, NavigConfig[] navConfs) { // Set the callback when the CurrentUser object has finished loading CurrentUser.AsyncLoadingFinished += (s, a) => { LoadNavigation(mainViewModels); RaisePropertyChanged("MainNavig"); }; CurrentViewModel = authVm; // Display the authentication view CurrentUser.AsyncLogin(); // Asynchronously log the user in loadingViewModel = loadingVm; // Load custom navigation informations NavigAttribute.RegisterConfigurations(navConfs); changeMainCmd = new Lazy<ICommand>(() => new RelayCommand<NavigConfig>(nc => CurrentMainNav = nc)); changeViewCmd = new Lazy<ICommand>(() => new RelayCommand<ViewModelFoundation>(vm => CurrentViewModel = vm)); }
/// <summary> /// Sets the view as a loading one and execute asynchronously the PreLoad method of IPreLoadable. /// Once loaded, it replaces the loading view by the freshly loaded ViewModel /// </summary> /// <param name="vm"></param> private async void AsyncLoadViewModel(IPreLoadable vm) { vm.IsPreLoadNeeded = false; // This ViewModel doesn't need loading anymore nowLoadingViewModel = currentViewModel; // Set the currently loading ViewModel currentViewModel = loadingViewModel; // Display the loading view vm.IsCurrentlyLoading = true; await Task.Factory.StartNew(vm.PreLoad); // Launch the preloading in another task vm.IsCurrentlyLoading = false; // Check if the view is a ILoadingViewModel and if it's currently in a loading state if(nowLoadingViewModel != null && !(nowLoadingViewModel as IPreLoadable).IsCurrentlyLoading) { currentViewModel = nowLoadingViewModel; // Replace the loading by the freshly loaded ViewModel nowLoadingViewModel = null; RaiseViewModelDisplayed(currentViewModel); RaisePropertyChanged("CurrentViewModel"); } }
/// <summary> /// Raise a ViewModelDisplayed event to alert the subscribers that a new ViewModel /// has been loaded into the application /// </summary> /// <param name="sender">The ViewModel that will be displayed</param> protected virtual void RaiseViewModelDisplayed(ViewModelFoundation sender) { EventHandler handler = sender.ViewModelDisplayed; if(handler != null) handler(sender, EventArgs.Empty); }