Я продолжаю изучать WPF и фокусируюсь на MVVM на данный момент и используя учебник "MVVM In a Box" Карла Шиффлетта. Но у вас есть вопрос об обмене данными между видами/режимами просмотра и тем, как он обновляет представление на экране. постскриптум Я еще не рассматривал МОК.
Ниже приведен снимок экрана моего MainWindow в тестовом приложении. Его разделение на 3 раздела (представления), заголовок, панель слайдов с кнопками, а остальная часть - как основной вид приложения. Цель приложения проста, войдите в приложение. При успешном входе в систему имя входа в систему должно исчезнуть, заменив его новым видом (т.е. OverviewScreenView), и соответствующие кнопки на слайде приложения должны стать видимыми.
Я вижу приложение как имеющее 2 ViewModels. Один для MainWindowView и один для LoginView, учитывая, что MainWindow не нуждается в командах для входа, поэтому я сохранил его отдельно.
Поскольку я еще не рассматривал IOC, я создал класс LoginModel, который является одноэлементным. Он содержит только одно свойство, которое является "public bool LoggedIn", и событие с именем UserLoggedIn.
Конструктор MainWindowViewModel регистрируется в событии UserLoggedIn. Теперь в LoginView, когда пользователь нажимает "Вход в LoginView", он вызывает команду LoginLogModel, которая, в свою очередь, если имя пользователя и пароль правильно введены, вызовет LoginModel и установит LoggedIn в значение true. Это приводит к срабатыванию события UserLoggedIn, которое обрабатывается в MainWindowViewModel, чтобы заставить представление скрыть LoginView и заменить его другим видом, то есть обзорным экраном.
Вопросы
Q1. Очевидный вопрос заключается в правильном использовании MVVM. т.е. поток управления выглядит следующим образом. LoginView → LoginViewViewModel → LoginModel → MainWindowViewModel → MainWindowView.
Q2. Предполагая, что пользователь вошел в систему, и MainWindowViewModel обработал событие. Как бы вы начали создавать новый View и помещать его там, где LoginView был, в равной степени, как вы собираетесь избавляться от LoginView, когда он не нужен. Будет ли свойство в MainWindowViewModel, например, "UserControl currentControl", которое устанавливается в LoginView или OverviewScreenView.
Q3. Если в MainWindow установлен элемент LoginView в дизайнере визуальной студии. Или, если он оставлен пустым и программно он понимает, что никто не зарегистрирован, поэтому после загрузки MainWindow он создает LoginView и показывает его на экране.
Некоторые примеры кода ниже, если это помогает с ответом на вопросы
XAML для MainWindow
<Window x:Class="WpfApplication1.MainWindow"
xmlns:local="clr-namespace:WpfApplication1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="372" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<local:HeaderView Grid.ColumnSpan="2" />
<local:ButtonsView Grid.Row="1" Margin="6,6,3,6" />
<local:LoginView Grid.Column="1" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</Window>
MainWindowViewModel
using System;
using System.Windows.Controls;
using WpfApplication1.Infrastructure;
namespace WpfApplication1
{
public class MainWindowViewModel : ObservableObject
{
LoginModel _loginModel = LoginModel.GetInstance();
private UserControl _currentControl;
public MainWindowViewModel()
{
_loginModel.UserLoggedIn += _loginModel_UserLoggedIn;
_loginModel.UserLoggedOut += _loginModel_UserLoggedOut;
}
void _loginModel_UserLoggedOut(object sender, EventArgs e)
{
throw new NotImplementedException();
}
void _loginModel_UserLoggedIn(object sender, EventArgs e)
{
throw new NotImplementedException();
}
}
}
LoginViewViewModel
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows.Input;
using WpfApplication1.Infrastructure;
namespace WpfApplication1
{
public class LoginViewViewModel : ObservableObject
{
#region Properties
private string _username;
public string Username
{
get { return _username; }
set
{
_username = value;
RaisePropertyChanged("Username");
}
}
#endregion
#region Commands
public ICommand LoginCommand
{
get { return new RelayCommand<PasswordBox>(LoginExecute, pb => CanLoginExecute()); }
}
#endregion //Commands
#region Command Methods
Boolean CanLoginExecute()
{
return !string.IsNullOrEmpty(_username);
}
void LoginExecute(PasswordBox passwordBox)
{
string value = passwordBox.Password;
if (!CanLoginExecute()) return;
if (_username == "username" && value == "password")
{
LoginModel.GetInstance().LoggedIn = true;
}
}
#endregion
}
}