Click here to Skip to main content
15,888,286 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hey,

I have a little trouble with a current project. I try to build up a one-window application with different pages to be load. The effect I try to archive is, to navigate (load) from one page to another, while the buttons for the navigation are part of the page itself. If I would have an extra navigation bar, besides my content presenter, it would be quite easy, but as the navigation is already part of the content, I do not find a good solution.

Currently, I have my MainWindow which looks like that:
C#
<Window.Resources>
  <DataTemplate DataType="{x:Type viewmodels:TitlePageVM}">
    <views:TitlePageView />
  </DataTemplate>
  // and further pages
</Window.Resources>

<Grid>
  <ContentControl Content="{Binding CurrentPageModel}" />
</Grid>

Inside the MainWindow.xaml.cs I set the DataContext to my MainWindowViewModel.
There I create an instance of all the pages inside the constructor and add them to an array inside of my singleton Mediator class, plus set the first page. The MainWindowViewModel also implements the INotifyPropertyChanged interface like this:
C#
public IPageViewModel CurrentPageVM
{
  get
  {
    return Mediator.Instance.CurrentPageViewModel;
  }
  set
  {
    Mediator.Instance.CurrentPageViewModel = value;
    OnPropertyChanged("CurrentPageVM");
  }
}

My Mediator class is a Singleton class and contains the array of all page instances, plus a CurrentPageVM property and a method to change the page:
C#
public List<IPageViewModel> PageVM
{
  get
  {
    //.. some code here
    return _pageVM;
  }
}

public IPageViewModel CurrentPageVM
{
  get { return _currentVM; }
  set { _currentVM = value; }
}

public void ChangeVM(IPageViewModel viewModel)
{
  //.. some code here
  CurrentPageVM = PageVM.FirstOrDefailt(vm => vm == viewModel)
}

On the pages I have the buttons for the navigation:
C#
<Button Content="Button" Command="{Binding ChangePageCommand}" />


The page has a view model as well, which implements the command:
C#
public ICommand ChangePageCommand
{
  get
  {
    if(_changePageCommand == null)
      _changePageCommand = new RelayCommand(() => Mediator.Instance.ChangeVM((IPageViewModel)Mediator.Instance.PageViewModel[1]), () => true);
    return _changePageCommand;
  }
}

And here is the actual problem. As the button gets clicked, the function ChangeVM is called from the mediator instance. It changes the CurrentVM and sets the _currentVM to the first member of the PageViewModel array, but the page does not change. Well, it actually can't, because the OnPropertyChanged method was never called, which is implemented inside the MainWindowVM. But how can I archive that?

I do not really want to give the Mediator class a callback or so and for me, this solution looks quite inelegant. Or maybe there is a much easier way, than using a Singleton mediator? I actually do not want to use frameworks, so I try to archive a functionality on my own.

Maybe someone has some suggestions?

Best regards,
Manic.

What I have tried:

1.) Building up a solution without Mediator class, but here I can't access the pages array from within the pages. Changing and loading a new page won't be possible.

2.) Using a Mediator class, which holds the page instances inside of an array. problem here is, the notify event will never be called since it is part of the MainWindowVM and not the Mediator class.
Posted
Updated 15-Oct-19 4:58am

Put your array of pages into a global static class. This makes your pages array available to any object.

Another option is to put all of the pages into the main form's xaml, and set their Visibility property to Visibility.Collapsed. At that point, all you have to do is manage the Visibility property when the user causes a new page to display.
 
Share this answer
 
If you want to navigate by ViewModel, then you need to link the View to the ViewModel in Resources. Then the view will display by association.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900