我正在继续学习WPF,并且目前专注于MVVM并使用Karl Shifflett的“MVVM In a Box”教程。但是有一个关于在views / viewmodels之间共享数据以及它如何在屏幕上更新视图的问题。附:我还没有报道过IOC。
下面是我在测试应用程序中的MainWindow的屏幕截图。它分为3个部分(视图),一个标题,一个带按钮的滑动面板,其余部分作为应用程序的主视图。应用程序的目的很简单,登录到应用程序。在成功登录后,登录视图应该被新视图(即OverviewScreenView)替换而消失,应用程序幻灯片上的相关按钮应该可见。
我认为应用程序有2个ViewModel。一个用于MainWindowView,另一个用于LoginView,因为MainWindow不需要登录命令,所以我将它保持分开。
由于我尚未介绍IOC,我创建了一个单独的LoginModel类。它只包含一个属性“public bool LoggedIn”,以及一个名为UserLoggedIn的事件。
MainWindowViewModel构造函数注册到事件UserLoggedIn。现在在LoginView中,当用户在LoginView上单击Login时,它会在LoginViewModel上引发一个命令,如果正确输入用户名和密码,则会调用LoginModel并将LoggedIn设置为true。这会导致UserLoggedIn事件触发,在MainWindowViewModel中处理该事件以使视图隐藏LoginView并用不同的视图(即概览屏幕)替换它。
问题
Q1。明显的问题,就是这样登录正确使用MVVM。即控制流程如下。 LoginView - > LoginViewViewModel - > LoginModel - > MainWindowViewModel - > MainWindowView。
Q2。假设用户已登录,并且MainWindowViewModel已处理该事件。您将如何创建新视图并将其放在LoginView所在的位置,同样如何在不需要时处理LoginView。 MainWindowViewModel中是否存在类似“UserControl currentControl”的属性,该属性设置为LoginView或OverviewScreenView。
Q3。 MainWindow是否应该在visual studio设计器中设置LoginView。或者它应该留空,并以编程方式确认没有人登录,因此一旦加载了MainWindow,它就会创建一个LoginView并在屏幕上显示它。
下面的一些代码示例是否有助于回答问题
MainWindow的XAML
<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
}
}
答案 0 :(得分:28)