Silverlight - 查看模型

在本章中,我们将介绍Silverlight软件开发中的一项重要技术,使用查看模型.

  • 视图模型是一个关键部分,它通过将视图与模型分开来引入一种称为分离演示的技术.

  • 查看模型提供实现单独演示的单向方式,我们将看到它们如何利用Silverlight的数据绑定来减少用户界面所需的代码量.

UI开发挑战

查看模型旨在解决某些问题在开发用户界面软件时频繁出现.也许最重要的一点是用户界面代码通常很难进行难以测试,尤其是自动单元测试.还存在可能影响代码持续灵活性和可维护性的代码质量问题.

  • 如果您遵循以下路径: Visual Studio的设计工具导致你失败的最小阻力,你最终可能会在后面的代码中添加太多的代码.

  • 看到大的很常见大量的应用程序功能被添加到后面的代码中.

  • 很少有开发人员真的计划将业务逻辑放入用户界面类,但因为那是Visual Studio提供了您的事件处理程序,它成为一个非常方便的地方来完成工作.

  • 人们普遍认为,如果软件更易于开发和维护,类具有明确定义且相当狭窄的职责.

  • 背后的代码是直接与组成用户界面的对象进行交互. .

  • 一旦你开始编写代码来决定应用程序在那里的行为,这往往会导致问题.

  • 应用程序逻辑不仅可以流入应该关注用户界面的代码,一些开发人员开始依赖控件,其他用户界面对象保持重要的应用程序状态.

  • 模型只需保存数据,视图只保存格式化日期,控制器(ViewModel)充当两者之间的联络人.控制器可以从视图中获取输入并将其放在模型上,反之亦然.

MVC

分隔演示文稿

为了避免将应用程序逻辑放在后面的代码或XAML中引起的问题,它是最好使用称为分离演示文稿的技术.让XAML和代码落后于直接使用用户界面对象所需的最小值,用户界面类还包含复杂交互行为,应用程序逻辑以及其他所有内容的代码,如左下图所示.

分隔演示文稿

分隔演示文稿的重要功能 :

  • 通过分隔显示,用户界面类更加简单.它当然有XAML,但背后的代码尽可能少.

  • 应用程序逻辑属于一个单独的类,通常称为模型.

  • 许多开发人员尝试使用数据绑定将XAML中的元素直接连接到模型中的属性.

  • 问题是模型完全关注应用程序的功能,而不是用户如何与应用程序交互.

  • 大多数用户界面都有一些不属于应用程序模型的状态.例如,如果您的用户界面使用拖放操作,则需要跟踪某些内容,例如现在正在拖动项目的位置,外观在可能的放置目标上移动时应该如何更改,以及这些放置目标也可能如何当项目被拖过它们时会发生变化.

  • 这种状态会变得非常复杂,需要进行全面测试.

  • 实际上,您通常希望在用户界面和模型之间使用其他类.这有两个重要的作用.

    • 首先,它使您的应用程序模型适应特定的用户界面视图.

    • 其次,它是任何重要的交互逻辑所在的地方,而且,我指的是让您的用户界面以您想要的方式运行所需的代码.

模型/视图/ViewModel

视图模型是分离演示方法的一个示例,但让我们清楚地了解每层中我们具有什么样的东西.有三层 :

  • 模型

  • 查看

  • ViewModel

模型

这是一个经典对象模型,包含与用户界面没有直接关系的普通C#类.

您通常希望您的Model代码能够在不引用任何用户界面库的情况下进行编译.实际上,您可能可以使用完全相同的源代码并将其编译为Silverlight应用程序,普通的.NET控制台应用程序,甚至服务器端Web代码.

模型中的类型应代表您的应用程序使用的概念.

查看

视图通常是UserControl,它可能是您的MainPage,或者它可能只是你页面的一部分.

在大多数Silverlight应用程序中,最好将用户界面拆分为定义UserControl的小块,或者每个块的View.

Silverlight应用程序在这方面并不是唯一的.显然,Silverlight特有的是View.您的用户界面越精细,往往就越好.你不仅不太可能绊倒在同一个文件上工作的其他开发人员,保持小而简单,自然会阻止导致类似意大利面条的代码的快捷方式.

例如,它是非常常见的是定义视图来表示列表中的单个项目.

ViewModel

最后,每个查看,您编写了 ViewModel .因此,这是 ViewModel 类的重要功能之一.

它存在于为特定视图提供服务. ViewModel 专门用于呈现内容的特定方式,例如列表中显示的特定数据项.

这就是为什么它被称为视图模型的;它适应底层模型,尤其适用于特定的视图.与模型一样, ViewModel 也是一个普通的C#类.它不需要从任何特定类型派生.

实际上,一些开发人员发现将一些常用功能放入基础ViewModel类很方便,但模式不要求这样做.特别是, ViewModel 不是从任何特定于Silverlight的类型派生的.但是,与模型不同,它可以在其属性中使用Silverlight类型.

例如,您的ViewModel可能会选择仅在特定条件下使用户界面的某些部分可见,因此您可能提供System.Windows.Visibility类型的属性,这是Silverlight元素用于其Visibility属性的类型.这使得可以将元素(例如面板)的可见性直接绑定到ViewModel.

示例

让我们看一下我们将使用模型 - 视图 - 视图模型(MVVM)方法的简单示例.

步骤1 : 创建一个新的Silverlight应用程序项目 SilverlightMVVMDemo .

步骤2 : 将三个文件夹(Model,ViewModel和Views)添加到项目中,如下所示.

SilverlightMVVMDemo

第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<Student> Students {  
         get;  
         set;  
      }  
		
      public void LoadStudents() { 
         ObservableCollection<Student> students = new ObservableCollection<Student>(); 
				
         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 文件夹添加 Silverlight用户控件,然后选择添加新项... .

Silverlight用户控制

步骤6 : 单击添加.现在您将看到XAML文件.将以下代码添加到 StudentView.xaml 文件中,该文件包含不同的UI元素.

<UserControl x:Class = "SilverlightMVVMDemo.Views.StudentView" 
   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" 
   mc:Ignorable = "d" 
   d:DesignHeight = "300" d:DesignWidth = "400">
   
   <Grid x:Name = "LayoutRoot" Background = "White">
	
      <StackPanel HorizontalAlignment = "Left">
		
         <ItemsControl ItemsSource = "{Binding Path=Students}">
			
            <ItemsControl.ItemTemplate>
				
               <DataTemplate> 
					
                  <StackPanel Orientation = "Horizontal"> 
                     <TextBox Text = "{Binding Path = FirstName, Mode = TwoWay}" 
                        Width = "100" Margin = "3 5 3 5"/> 
								
                     <TextBox Text = "{Binding Path = LastName, Mode = TwoWay}"  
                        Width = "100" Margin = "0 5 3 5"/> 
								
                     <TextBlock  Text = "{Binding Path = FullName, Mode=OneWay}" 
                        Margin = "0 5 3 5"/> 
								
                  </StackPanel>
						
               </DataTemplate> 
					
            </ItemsControl.ItemTemplate>
				
         </ItemsControl> 
			
      </StackPanel> 
		
   </Grid> 
	
</UserControl>

第7步 : 现在将 StudentView 添加到 MainPage.xaml 文件中,如下所示.

<UserControl x:Class = "SilverlightMVVMDemo.MainPage" 
   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:views = "clr-namespace:SilverlightMVVMDemo.Views" 
   mc:Ignorable = "d" 
   d:DesignHeight = "576.316" d:DesignWidth = "863.158"> 
   
   <Grid x:Name = "LayoutRoot" Background = "White"> 
      <views:StudentView x:Name = "StudentViewControl" Loaded = "StudentViewControl_Loaded"/> 
   </Grid> 
	
</UserControl>

第8步 : 以下是 MainPage.xaml.cs 文件中已加载事件的实现,该文件将从 ViewModel 中更新视图 b>.

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步 : 编译并执行上述代码后,您将在网页上看到以下输出.

添加学生视图

UI与ViewModel

MVVM方法中最困难的部分之一就是找出分界线的位置.并不总是很明显哪些东西属于哪里.

  • 特别是,一些用户界面元素提供了功能,根据一个严格的视图应该可以说属于ViewModel.

  • 一般来说,视图中实现的所有行为都不是这样的 ViewModel 友好.

  • 部分原因是没有任何标准方法可以将ViewModel行为打包以供重用,尤其是您想使用设计环境,例如Visual Studio或Blend.

MVVM的优点

MVVM提供以下优点 :

  • 表达问题的分离(View,ViewModel,Model)

  • 清理可测试和可管理的代码.可以在单元测试中包含表示层逻辑.

  • 代码背后没有代码,因此表示层和逻辑松散耦合.

  • 更好的数据绑定方式.

MVVM的缺点

对于简单的UI,MVVM可能是一种过度杀伤力.当我们有复杂的数据绑定时,调试会有点困难.