ManicPumpkin Ответов: 2

C# WPF MVVM навигация по страницам на каждой странице, без фреймворка


Эй,

У меня небольшие проблемы с текущим проектом. Я пытаюсь создать однооконное приложение с разными страницами для загрузки. Эффект, который я пытаюсь архивировать, заключается в том, чтобы перемещаться (загружать) с одной страницы на другую, в то время как кнопки для навигации являются частью самой страницы. Если бы у меня была дополнительная панель навигации, помимо моего презентера контента, это было бы довольно легко, но поскольку навигация уже является частью контента, я не нахожу хорошего решения.

В настоящее время у меня есть мое главное окно, которое выглядит так:
<Window.Resources>
  <DataTemplate DataType="{x:Type viewmodels:TitlePageVM}">
    <views:TitlePageView />
  </DataTemplate>
  // and further pages
</Window.Resources>

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

Внутри MainWindow.xaml.cs я установил DataContext в свою MainWindowViewModel.
Там я создаю экземпляр всех страниц внутри конструктора и добавляю их в массив внутри моего класса singleton Mediator, а также устанавливаю первую страницу. MainWindowViewModel также реализует интерфейс INotifyPropertyChanged следующим образом:
public IPageViewModel CurrentPageVM
{
  get
  {
    return Mediator.Instance.CurrentPageViewModel;
  }
  set
  {
    Mediator.Instance.CurrentPageViewModel = value;
    OnPropertyChanged("CurrentPageVM");
  }
}

Мой класс посредника является Одноэлементным классом и содержит массив всех экземпляров страницы, а также свойство CurrentPageVM и метод для изменения страницы:
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)
}

На страницах у меня есть кнопки для навигации:
<Button Content="Button" Command="{Binding ChangePageCommand}" />


На странице также есть модель представления, которая реализует команду:
public ICommand ChangePageCommand
{
  get
  {
    if(_changePageCommand == null)
      _changePageCommand = new RelayCommand(() => Mediator.Instance.ChangeVM((IPageViewModel)Mediator.Instance.PageViewModel[1]), () => true);
    return _changePageCommand;
  }
}

И вот в чем собственно проблема. При нажатии на кнопку функция ChangeVM вызывается из экземпляра посредника. Он изменяет CurrentVM и устанавливает _currentVM в первый член массива PageViewModel, но страница не изменяется. Ну, на самом деле это невозможно, потому что метод OnPropertyChanged никогда не вызывался, который реализован внутри MainWindowVM. Но как я могу это заархивировать?

Я действительно не хочу давать классу посредника обратный вызов или что-то в этом роде, и для меня это решение выглядит довольно неэлегантным. Или, может быть, есть гораздо более простой способ, чем использование Одноэлементного посредника? На самом деле я не хочу использовать фреймворки, поэтому стараюсь архивировать функциональность самостоятельно.

Может быть, у кого-то есть какие-то предложения?

С уважением,
Маниакальный.

Что я уже пробовал:

1.) Создание решения без класса посредника, но здесь я не могу получить доступ к массиву страниц изнутри страниц. Изменить и загрузить новую страницу будет невозможно.

2.) Использование класса-посредника, который содержит экземпляры страниц внутри массива. проблема здесь в том, что событие notify никогда не будет вызвано, так как оно является частью MainWindowVM, а не класса-посредника.

2 Ответов

Рейтинг:
2

Graeme_Grant

Если вы хотите перемещаться по ViewModel, то вам нужно связать представление с ViewModel в Resources. Затем представление будет отображаться по ассоциации.


Рейтинг:
1

#realJSOP

Поместите свой массив страниц в глобальный статический класс. Это делает Ваш массив страниц доступным для любого объекта.

Другой вариант-поместить все страницы в xaml основной формы и установить их Visibility собственность на Visibility.Collapsed В этот момент все, что вам нужно сделать, это управлять Visibility свойство, когда пользователь вызывает отображение новой страницы.