Page Navigation using MVVM in Store App

后端 未结 5 1006
我在风中等你
我在风中等你 2020-11-30 02:55

I\'m having a serious headache with this problem. I really dislike store apps but am forced to use it in this case. I\'ve only worked with XAML for a few weeks.

My q

5条回答
  •  猫巷女王i
    2020-11-30 03:19

    I don't really like when a ViewModel references Views to navigate to. So I prefer to a ViewModel-first approach. By using ContentControls, DataTemplates for ViewModel types & some kind of navigation pattern in my ViewModels.

    My navigation looks like this:

    [ImplementPropertyChanged]
    public class MainNavigatableViewModel : NavigatableViewModel
    {
        public ICommand LoadProfileCommand { get; private set; }
    
        public ICommand OpenPostCommand { get; private set; }
    
        public MainNavigatableViewModel ()
        {
            LoadProfileCommand = new RelayCommand(() => Navigator.Navigate(new ProfileNavigatableViewModel()));
            OpenPostCommand = new RelayCommand(() => Navigator.Navigate(new PostEditViewModel { Post = SelectedPost }), () => SelectedPost != null);
        }
    }
    

    My NavigatableViewModel looks like:

    [ImplementPropertyChanged]
    public class NavigatableViewModel
    {
        public NavigatorViewModel Navigator { get; set; }
    
        public NavigatableViewModel PreviousViewModel { get; set; }
    
        public NavigatableViewModel NextViewModel { get; set; }
    
    }
    

    And my Navigator:

    [ImplementPropertyChanged]
    public class NavigatorViewModel
    {
        public NavigatableViewModel CurrentViewModel { get; set; }
    
        public ICommand BackCommand { get; private set; }
    
        public ICommand ForwardCommand { get; private set; }
    
        public NavigatorViewModel()
        {
            BackCommand = new RelayCommand(() =>
            {
                // Set current control to previous control
                CurrentViewModel = CurrentViewModel.PreviousViewModel;
            }, () => CurrentViewModel != null && CurrentViewModel.PreviousViewModel != null);
    
            ForwardCommand = new RelayCommand(() =>
            {
                // Set current control to next control
                CurrentViewModel = CurrentViewModel.NextViewModel;
            }, () => CurrentViewModel != null && CurrentViewModel.NextViewModel != null);
        }
    
        public void Navigate(NavigatableViewModel newViewModel)
        {
            if (newViewModel.Navigator != null && newViewModel.Navigator != this)
                throw new Exception("Viewmodel can't be added to two different navigators");
    
            newViewModel.Navigator = this;
    
            if (CurrentViewModel != null)
            {
                CurrentViewModel.NextViewModel = newViewModel;
            }
    
            newViewModel.PreviousViewModel = CurrentViewModel;
            CurrentViewModel = newViewModel;
        }
    }
    

    My MainWindows.xaml:

    
        
            
            
    
            

    App.xaml.cs:

    public partial class App
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
    
            new MainWindow {DataContext = new MyAppViewModel()}.Show();
        }
    }
    

    MyAppViewModel:

    [ImplementPropertyChanged]
    public class MyAppViewModel
    {
        public NavigatorViewModel Navigator { get; set; }
    
        public MyAppViewModel()
        {
            Navigator = new NavigatorViewModel();
            Navigator.Navigate(new MainNavigatableViewModel());
        }
    }
    

    App.xaml:

            
                
            
            
                
            
    

    The downside is that you have more ViewModel-code which manages the state of what you are looking at. But obviously that is also a huge advantage in terms of Testability. And of course your ViewModels do not need to depend on your Views.

    Plus I use Fody/PropertyChanged, that's what the [ImplementPropertyChanged] is about. Keeps me from writing OnPropertyChanged code.

提交回复
热议问题