Я пытаюсь изучить MVVM, но нахожу это кошмаром, пытаясь понять, как правильно перемещаться между представлениями в приложении с помощью MVVM. Через некоторое время, исследуя и пытаясь понять разные методы, я столкнулся с подходом от Rachel Lim's blog. Этот метод использует ViewModel для самого приложения и отслеживает состояние приложения, такое как текущая страница. Я считаю, что это будет хороший подход для моего приложения.Как изменить вид главного окна из всплывающего окна
Теперь перейти на мою проблему ..
То, что я хочу достичь
Я хочу, чтобы приложение, которое имеет один главный вид приложения, который будет хранить LoginView и HomeView как DataTemplates и иметь контроль содержимого, который устанавливает LoginView как представление, отображаемое при запуске приложения. В LoginView будет кнопка, которая при нажатии откроет другое окно с кнопкой. Когда кнопка во всплывающем окне нажата, я хочу изменить вид в главном окне приложения из LoginView в HomeView.
То, что я до сих пор
У меня есть набор вверх ApplicationView, который работает отлично.
<Window x:Class="WPF_Navigation_Practice.Views.ApplicationView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ignore="http://www.galasoft.ch/ignore"
xmlns:vm="clr-namespace:WPF_Navigation_Practice.ViewModels"
xmlns:views="clr-namespace:WPF_Navigation_Practice.Views"
mc:Ignorable="d ignore"
DataContext="{StaticResource ApplicationViewModel}">
<Window.Resources>
<DataTemplate DataType="{x:Type vm:LoginViewModel}">
<views:LoginView />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:HomeViewModel}">
<views:HomeView />
</DataTemplate>
</Window.Resources>
<Grid>
<ContentControl Content="{Binding CurrentPageViewModel}" />
</Grid>
</Window>
И установили ApplicationViewModel следующим образом. Установка текущей страницы в LoginViewModel.
using System.Collections.Generic;
using System.Linq;
using System.Windows.Input;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using WPF_Navigation_Practice.Interfaces;
namespace WPF_Navigation_Practice.ViewModels
{
/// <summary>
/// This class contains properties that a View can data bind to.
/// <para>
/// See http://www.galasoft.ch/mvvm
/// </para>
/// </summary>
public class ApplicationViewModel : ViewModelBase
{
#region Fields
private ICommand _changePageCommand;
private IPageViewModel _currentPageViewModel;
private List<IPageViewModel> _pageViewModels;
#endregion
public ApplicationViewModel()
{
// Add available pages
PageViewModels.Add(new LoginViewModel());
PageViewModels.Add(new HomeViewModel());
PageViewModels.Add(new CodeViewModel());
// Set starting page
CurrentPageViewModel = PageViewModels[0];
}
#region Properties/Commands
public ICommand ChangePageCommand
{
get
{
if (_changePageCommand == null)
{
_changePageCommand = new RelayCommand<object>(
p => ChangeViewModel((IPageViewModel)p),
p => p is IPageViewModel);
}
return _changePageCommand;
}
}
public List<IPageViewModel> PageViewModels
{
get
{
if (_pageViewModels == null)
_pageViewModels = new List<IPageViewModel>();
return _pageViewModels;
}
}
public IPageViewModel CurrentPageViewModel
{
get
{
return _currentPageViewModel;
}
set
{
if (_currentPageViewModel != value)
{
_currentPageViewModel = value;
RaisePropertyChanged("CurrentPageViewModel");
}
}
}
#endregion
#region Methods
private void ChangeViewModel(IPageViewModel viewModel)
{
if (!PageViewModels.Contains(viewModel))
PageViewModels.Add(viewModel);
CurrentPageViewModel = PageViewModels
.FirstOrDefault(vm => vm == viewModel);
}
#endregion
}
}
При запуске приложения оно будет отображаться мое главное окно приложения, которое отображает LoginView, который является UserControl и устанавливается как currentPageViewModel с ContentPresenter.
Когда нажата кнопка в UserView UserControl, она откроет другое окно. Как показано на рисунке ниже.
Вот XAML для этого окна.
<Window x:Class="WPF_Navigation_Practice.Views.CodeView"
x:Name="CodeWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ignore="http://www.galasoft.ch/ignore"
xmlns:z="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:viewModels="clr-namespace:WPF_Navigation_Practice.ViewModels"
mc:Ignorable="d ignore"
d:DesignWidth="623.224" d:DesignHeight="381.269"
DataContext="{Binding CodeViewModel, Source={StaticResource ApplicationViewModel}}">
<Grid>
<Button Content="Ok"
HorizontalAlignment="Left"
Margin="235,166,0,0"
VerticalAlignment="Top"
Width="138"
FontSize="20"
Height="67"/>
<Label Content="Second Window" HorizontalAlignment="Left" Margin="166,56,0,0" VerticalAlignment="Top" FontSize="36"/>
</Grid>
Моя проблема
То, что я хочу достичь, когда кнопка «Ok» в окне secondView нажата, я хочу, чтобы изменить currentPageViewModel в ApplicationView окна из LoginView, чтобы отобразить HomeView, но я смущен тем, как я буду добиваться этого. Любая помощь будет принята с благодарностью.
Я могу дать loginview событие LoggedIn, на которое подписывается основной вид. Затем, когда это поднято, основное представление может сообщить о том, что кто-то вошел в систему, установив для него свойство (это == приложение vm), вызывая метод, что угодно. Должна быть One Viewmodel для правильного использования всех, кто принимает решение о том, что делать, когда пользователь входит в систему. Я предполагаю, что это модель представления приложения. –
MVVM честно не хорошо разработан для создания нескольких окон (включая диалоги и т. Д.). Если возможно, используйте одно окно и подключите различные UserControls (каждый из них считается View). – Jai
Любые проблемы с передачей главного окна в качестве параметра конструктору всплывающего окна и установка вида из него с использованием свойства главного окна. – AnjumSKhan