Tell me, how is it better to organize page navigation, if mvvm light is used? assumed to be the main window, the default page and a few more, all in the main window

  • one
    The question is given a good answer, you can leave it open. Although in the future should clearly describe the difficulties encountered. - Athari pm

2 answers 2

We declare the interface:

public interface INavigationService { void Navigate(Type type); void Navigate(Type type, object parameter); void EnsureNavigated(Type pageType, object parameter); bool CanGoBack { get; } bool CanGoForward { get; } void GoBack(); void GoForward(); IView CurrentView { get; } } 

We implement this interface:

 using System; using System.Collections.Generic; using System.Threading.Tasks; using Windows.UI.Xaml.Controls; public class NavigationService : INavigationService { private readonly Frame _frame; public NavigationService(Frame frame) { _frame = frame; _frame.Navigated += OnFrameNavigated; } private void OnFrameNavigated(object sender, Windows.UI.Xaml.Navigation.NavigationEventArgs e) { var view = e.Content as IView; if (view == null) return; var navMsg = new NavigationMessage() { Sender = this, NewView = view, Parameter = e.Parameter, NavigationMode = (int)e.NavigationMode }; EventManager.Current.Publish(navMsg); var viewModel = view.ViewModel; if (viewModel != null) viewModel.Initialise(e.Parameter); } public void Navigate(Type pageType) { DisposePreviousView(); _frame.Navigate(pageType); } public void Navigate(Type pageType, object parameter) { DisposePreviousView(); _frame.Navigate(pageType, parameter); } private void DisposePreviousView() { var currentView = this.CurrentView; var currentViewDisposable = currentView as IDisposable; if (currentViewDisposable != null) { currentViewDisposable.Dispose(); currentViewDisposable = null; } } public void EnsureNavigated(Type pageType, object parameter) { var currentView = this.CurrentView; if (currentView == null || currentView.GetType() != pageType) { Navigate(pageType, parameter); } } public IView CurrentView { get { return _frame.Content as IView; } } public bool CanGoBack { get { return _frame != null && _frame.CanGoBack; } } public void GoBack() { if (_frame != null && _frame.CanGoBack) _frame.GoBack(); } public bool CanGoForward { get { return _frame != null && _frame.CanGoForward; } } public void GoForward() { if (_frame != null && _frame.CanGoForward) _frame.GoForward(); } } 

IView:

 public interface IView : IDisposable { IViewModel ViewModel { get; } void Refresh(); } 

IViewModel:

 public interface IViewModel : INotifyPropertyChanged, IDisposable { void Initialise(object parameter); string ViewTitle { get; } void Refresh(); } 

In HAML, add a frame element: <Frame x:Name="ContentFrame" />

In the back: var _navigationService = new NavigationService(this.ContentFrame);

Those. like this:

 public HomePage() { this.InitializeComponent(); var _navigationService = new NavigationService(this.ContentFrame); DataContext = new HomePageViewModel(_navigationService); } 

I also recommend reading this article.

  • Thank you so much for the detailed answer! - bmo
  • one
    @bmo if the answer helped you solve your problem, then click the check mark in front of my answer. - Mstislav Pavlov
  • I would love to ply, but karma does not allow ( - bmo
  • one
    @bmo I'm not talking about plucking, but about tagging the answer with the right :) - Mstislav Pavlov
  • one
    As it turned out, the code given by me is somewhat outdated for the current studio versions. Use the link at the end, there is a more relevant example. - Mstislav Pavlov

found such a solution:

xaml

  xmlns:viewModels="clr-namespace:iim.ViewModels" xmlns:views="clr-namespace:iim.Views" <Window.DataContext> <viewModels:MainViewModel x:Name="xxx"/> </Window.DataContext> <Window.Resources> <DataTemplate DataType="{x:Type viewModels:GridViewModel}"> <views:GridVieww /> </DataTemplate> </Window.Resources> <DockPanel> <DockPanel.Resources> <viewModels:MainViewModel x:Key="xxx" /> <viewModels:BoolToVis x:Key="b" /> </DockPanel.Resources> <StackPanel DockPanel.Dock="Top"> <Button Content="Excel" Command="{Binding ShowExcelView}"></Button> </StackPanel> <ContentControl x:Name="Viewss" DockPanel.Dock="Bottom" Content="{Binding SelectedViewModel}"/> 

MainViewModel.cs

  using GalaSoft.MvvmLight; using GalaSoft.MvvmLight.Command; public class MainViewModel : ViewModelBase { private object selectedViewModel; public object SelectedViewModel { get { return selectedViewModel; } set { selectedViewModel = value; RaisePropertyChanged(() => SelectedViewModel); } } private ICommand _showGridView; public ICommand ShowGridView { get { return _showGridView ?? (_showGridView = new RelayCommand(() => { SelectedViewModel = new GridVieww(); })); } } }