📅  最后修改于: 2020-11-19 08:38:16             🧑  作者: Mango
在本章中,我们将寻求在Silverlight软件开发的重要技术,使用视图模型的。
视图模型是关键部分,它通过将视图与模型分开来引入一种称为分离表示的技术。
视图模型提供了一种实现分离表示的方式,我们将看到它们如何利用Silverlight的数据绑定来减少用户界面中所需的代码量。
视图模型旨在解决开发用户界面软件时经常出现的某些问题。也许最重要的一个原因是用户界面代码通常很难进行难于测试,尤其是在自动化单元测试中。还有一些代码质量问题,可能会影响代码的持续灵活性和可维护性。
如果您遵循Visual Studio设计工具导致您阻力最小的方法,那么最终可能会将太多的代码放到后面的代码中。
看到大量的应用程序功能被添加到后面的代码中是很常见的。
很少有开发人员真正打算将业务逻辑放入用户界面类中,但是由于这是Visual Studio放置事件处理程序的地方,因此它变得太方便了,无法完成任务。
人们普遍接受的是,如果类具有明确定义的职责和相对狭窄的职责,则软件更易于开发和维护。
背后的工作代码是在需要时直接与构成用户界面的对象进行交互。
一旦开始放置代码,就可以决定应用程序在其中的行为方式,这往往会导致问题。
应用程序逻辑不仅会流入本应与用户界面有关的代码中,一些开发人员开始依赖控件,而其他用户界面对象也将保持重要的应用程序状态。
该模型仅保存数据,视图仅保存格式化的日期,而控制器(ViewModel)充当两者之间的联络人。控制器可能会从视图中获取输入并将其放置在模型上,反之亦然。
为了避免由于将应用程序逻辑放在代码后方或XAML中而导致的问题,最好使用一种称为分离表示的技术。 XAML和代码落后于直接使用用户界面对象所需的最低限度,因此用户界面类还包含用于复杂交互行为,应用程序逻辑以及其他所有内容的代码,如下左侧所示。
独立演示的重要功能-
使用分离的表示,用户界面类要简单得多。它当然具有XAML,但是其背后的代码作用却很小。
应用程序逻辑属于一个单独的类,该类通常称为模型。
许多开发人员尝试使用数据绑定将XAML中的元素直接连接到模型中的属性。
问题在于模型完全与应用程序的功能有关,而不与用户如何与应用程序交互有关。
大多数用户界面都具有某些不属于应用程序模型的状态。例如,如果您的用户界面使用拖放操作,则需要跟踪某些内容,例如当前被拖动的项目,在可能的放置目标上移动时其外观应如何变化以及这些放置目标也可能如何将项目拖动到它们上方时更改。
这种状态可能会变得异常复杂,需要进行全面测试。
实际上,您通常希望在用户界面和模型之间放置一些其他类。这有两个重要作用。
首先,它使您的应用程序模型适合特定的用户界面视图。
其次,这是任何不平凡的交互逻辑存在的地方,而且,我的意思是使用户界面按照您想要的方式运行所需的代码。
视图模型是分离的表示方法的一个示例,但是让我们清楚地知道每一层中都有什么样的东西。三层-
这是一个经典的对象模型,包括与用户界面没有直接关系的普通C#类。
通常,您希望Model代码能够在不引用任何用户界面库的情况下进行编译。实际上,您可能可以使用完全相同的源代码并将其编译为Silverlight应用程序,普通的.NET Console应用程序甚至服务器端Web代码。
模型中的类型应表示您的应用程序所使用的概念。
视图通常是一个UserControl,它可能是您的MainPage,也可能只是页面的一部分。
在大多数Silverlight应用程序中,最好将用户界面拆分为小块,以定义一个UserControl或每块View。
Silverlight应用程序在这方面不是唯一的。视图显然是Silverlight特有的。用户界面越细粒度,情况就越好。您不仅不大可能绊倒其他使用相同文件的开发人员,而且保持小巧而简单的做法自然会阻碍导致产生意大利面条式代码的快捷方式。
例如,定义视图以表示列表中的单个项目是很常见的。
最后,为每个View编写一个ViewModel 。因此,这是ViewModel类的重要功能之一。
存在它是为特定视图服务。 ViewModel专门用于呈现事物的特定方式,例如List中显示的特定数据项。
这就是为什么它被称为ViewModel的原因;它适应基础模型,特别是针对特定视图。与Model一样, ViewModel也是普通的C#类。它不需要从任何特定类型派生。
碰巧的是,一些开发人员发现将一些常用功能放入基ViewModel类很方便,但是模式并不需要。特别是,您的ViewModel不会派生自任何Silverlight特定类型。但是,与模型不同,它可以在其属性中使用Silverlight类型。
例如,您的ViewModel可能选择仅在某些条件下使用户界面的某些部分可见,因此您可能提供类型为System.Windows.Visibility的属性,该属性是Silverlight元素用于其Visibility属性的类型。这样就可以将面板等元素的可见性直接绑定到ViewModel。
让我们看一个简单的示例,在该示例中将使用Model-View-ViewModel(MVVM)方法。
步骤1-创建一个新的Silverlight应用程序项目SilverlightMVVMDemo 。
步骤2-如下图所示,将三个文件夹(Model,ViewModel和Views)添加到您的项目中。
步骤3-在Model文件夹中添加StudentModel类,并将以下代码粘贴到该类中。
using System.ComponentModel;
namespace SilverlightMVVMDemo.Model {
public class StudentModel {}
public class Student : INotifyPropertyChanged {
private string firstName;
private string lastName;
public string FirstName {
get { return firstName; }
set {
if (firstName != value) {
firstName = value;
RaisePropertyChanged("FirstName");
RaisePropertyChanged("FullName");
}
}
}
public string LastName {
get { return lastName; }
set {
if (lastName != value) {
lastName = value;
RaisePropertyChanged("LastName");
RaisePropertyChanged("FullName");
}
}
}
public string FullName {
get {
return firstName + " " + lastName;
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property) {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
}
步骤4-将另一个StudentViewModel类添加到ViewModel文件夹中,然后粘贴以下代码。
using SilverlightMVVMDemo.Model;
using System.Collections.ObjectModel;
namespace SilverlightMVVMDemo.ViewModel {
public class StudentViewModel {
public ObservableCollection Students {
get;
set;
}
public void LoadStudents() {
ObservableCollection students = new ObservableCollection();
students.Add(new Student { FirstName = "Mark", LastName = "Allain" });
students.Add(new Student { FirstName = "Allen", LastName = "Brown" });
students.Add(new Student { FirstName = "Linda", LastName = "Hamerski" });
Students = students;
}
}
}
步骤5-通过右键单击Views文件夹并选择Add New Item…来添加Silverlight用户控件。
步骤6-单击添加。现在,您将看到XAML文件。将以下代码添加到StudentView.xaml文件,该文件包含不同的UI元素。
步骤7-现在将StudentView添加到您的MainPage.xaml文件中,如下所示。
步骤8-这是MainPage.xaml.cs文件中Loaded事件的实现,该文件将更新ViewModel中的View 。
using System.Windows;
using System.Windows.Controls;
namespace SilverlightMVVMDemo {
public partial class MainPage : UserControl {
public MainPage() {
InitializeComponent();
}
}
private void StudentViewControl_Loaded(object sender, RoutedEventArgs e) {
SilverlightMVVMDemo.ViewModel.StudentViewModel
studentViewModelObject = new SilverlightMVVMDemo.ViewModel.
StudentViewModel();
studentViewModelObject.LoadStudents();
StudentViewControl.DataContext = studentViewModelObject;
}
}
步骤9-编译并执行上述代码后,您将在网页上看到以下输出。
MVVM方法中最困难的部分之一就是确定分界线应该在哪里。哪些事物属于哪里并不总是很明显。
特别是,某些用户界面元素提供了功能,根据严格的View,可以说它们应该属于ViewModel。
通常,并非所有在View中实现的行为都对ViewModel友好。
造成这种情况的部分原因是,没有任何标准方法可以打包ViewModel行为以进行重用,尤其是如果您要使用设计环境(例如Visual Studio或Blend)时,则没有这种方法。
MVVM具有以下优点-
表示关注点分离(视图,ViewModel,模型)
清除可测试和可管理的代码。可以在单元测试中包括表示层逻辑。
代码背后没有代码,因此表示层和逻辑是松散耦合的。
更好的数据绑定方式。
对于简单的UI,MVVM可能会显得过大。当我们具有复杂的数据绑定时,调试会有些困难。