Windows Phone Mango:MVVM十分钟入门
在这篇文章中,我将谈一下在windows phone 7.1 Mango应用程序中使用MVVM设计模式。用较少的理论、更多的示例,在10分钟内来解释MVVM模式。
在开始之前,先简短介绍一下什么是MVVM:Model-View-ViewModel (MVVM)模式提供了一种灵活的方式,通过将应用程序分隔成三部分来创建windows phone应用程序。
a:View:放置XAML文件。
b:ViewModel:放置连接UI和数据的显示逻辑层。
c:放置数据模型和业务对象。
有关更多信息,看参阅官方MSDN文档。
为什么选择MVVM?有什么好处?
-      视图和显示逻辑层分离:从显示逻辑层分离出来View/XAML,可以使开发者只关注Code,而设计人员只关注XAML。 
-      自动单元测试:视图/逻辑分离大大改进了表现逻辑层的自动单元测试。 
-      代码重用:因为显示逻辑层在独立的组件或类中,和View(XAML)分离开来,你可以按照你喜欢的方式,通过继承和组合使它们结合起来。 
-      设计时数据支持: 你可以在Blend中看到UI的样子,也就是说,设计人员可以使用样本数据来测试UI,甚至可以模拟实际场景数据。 
-      多视图: 依据用户角色,同一ViewModel可以在不同的多视图中展现。 
入门开始:
我们需要Windows Phone 7.1 Mango工程项目。在这个实例中,我们会使用上篇文章 为Windows Phone Mango MVVM 应用创建可复用 ICommand 实现类 所创建的DelegateCommand。请注意:commanding是伴随mango更新的新特性。(commanding意味着一些控件不支持Commands)。
MODEL
首先我们需要定义Model。在示例中,我们创建Person类,有两个属性:Name和Age。在这里,最重要的就是要实现INotifyPropertyChanged接口,因为,当Person对象发现变化时,需要通知给UI。(本例中,当按下Save Changes时,更新ListBox,更多信息参阅下面部分中的View)
using System;
  using System.Net;
  using System.Windows;
  using System.Windows.Controls;
  using System.Windows.Documents;
  using System.Windows.Ink;
  using System.Windows.Input;
  using System.Windows.Media;
  using System.Windows.Media.Animation;
  using System.Windows.Shapes;
  using System.ComponentModel;
  namespace WPMangoMVVMSample
  {
  public class Person : INotifyPropertyChanged
    {
  private string name;
private int age;
public string Name
        {
  get
            {
                  return name;
  }
set
            {
  if (this.name != value)
                {
  this.name = value;
this.RaisePropertyChanged("Name");
}
}
}
public int Age
        {
  get
            {
  return this.age;
}
set
            {
  if (this.age != value)
                {
  this.age = value;
this.RaisePropertyChanged("Age");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
        {
              PropertyChangedEventHandler handler = this.PropertyChanged;
  if (handler != null)
            {
  handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
VIEW MODEL
下一步就是创建PersonViewModel,主要包含以下部分:
- SaveChangesCommand - 保存用户选择Person对象所引发的修改。
- LoadDataCommand - 此命令是用来填充ObservableCollection(Person对象)。
- SelectedName - 此属性表示选中的Person对象的名称。
- SelectedAge - 此属性表示选中的Person对象的年龄。
- SelectedPerson - 此属性表示所选中的Person对象。
PersonViewModel也实现了INotifyPropertyChanged,所有当某些属性更新时,UI会接到通知。 代码如下:
using System;
  using System.Net;
  using System.Windows;
  using System.Windows.Controls;
  using System.Windows.Documents;
  using System.Windows.Ink;
  using System.Windows.Input;
  using System.Windows.Media;
  using System.Windows.Media.Animation;
  using System.Windows.Shapes;
  using System.ComponentModel;
  using System.Collections.ObjectModel;
  namespace WPMangoMVVMSample
  {
  public class PersonViewModel : INotifyPropertyChanged
    {
  private string name;
private int age;
        private ObservableCollection<Person> personDataSource;
          private ICommand loadDataCommand;
          private ICommand saveChangesCommand;
          public PersonViewModel()
          {
  this.loadDataCommand = new DelegateCommand(this.LoadDataAction);
this.saveChangesCommand = new DelegateCommand(this.SaveChangesAction);
}
private void LoadDataAction(object p)
        {
  this.DataSource.Add(new Person() { Name = "John", Age = 32 });
this.DataSource.Add(new Person() { Name = "Kate", Age = 27 });
this.DataSource.Add(new Person() { Name = "Sam", Age = 30 });
}
private void SaveChangesAction(object p)
        {
  if (this.SelectedPerson != null)
            {
  this.SelectedPerson.Name = this.name;
this.SelectedPerson.Age = this.age;
}
}
        public ICommand LoadDataCommand
          {
  get
            {
  return this.loadDataCommand;
}
}
        public ICommand SaveChangesCommand
          {
  get
            {
  return this.saveChangesCommand;
}
}
        public ObservableCollection<Person> DataSource
          {
  get
            {
  if (this.personDataSource == null)
                {
  this.personDataSource = new ObservableCollection<Person>();
}
return this.personDataSource;
}
}
public string SelectedName
        {
  get
            {
  if (this.SelectedPerson != null)
                {
  return this.SelectedPerson.Name;
}
return string.Empty;
}
set
            {
  this.name = value;
}
}
public int SelectedAge
        {
  get
            {
  if (this.SelectedPerson != null)
                {
  return this.SelectedPerson.Age;
}
                return 0;
  }
set
            {
  this.age = value;
}
}
        private Person selectedPerson;
          public Person SelectedPerson
          {
  get
            {
  return this.selectedPerson;
}
set
            {
  if (this.selectedPerson != value)
                {
  this.selectedPerson = value;
if (this.selectedPerson != null)
                    {
  this.name = this.selectedPerson.Name;
this.age = this.selectedPerson.Age;
}
this.RaisePropertyChanged("SelectedName");
this.RaisePropertyChanged("SelectedAge");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
        {
              PropertyChangedEventHandler handler = this.PropertyChanged;
  if (handler != null)
            {
  handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
VIEW
最后一步就是创建View。 我们仍然使用 MainPage.xaml。我们将创建:
- "LoadData" 按钮: 调用LoadDataCommand填充数据源。
- ListBox 绑定PersonViewModel,两个TextBox用来编辑选择的Person对象: 姓名和年龄。
- "Save Changes" 调用SaveChangesCommand保存修改信息。
注意: TextBox的Binding 数据流向:Mode=TwoWay ,可以编辑和更新值。
<StackPanel x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Button Content="LoadData" Command="{Binding LoadDataCommand}" />
<ListBox ItemsSource="{Binding DataSource}" SelectedItem="{Binding SelectedPerson, Mode=TwoWay}" Height="100">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Name:"/>
<TextBlock Text="{Binding Name}" />
<TextBlock Text="Age:" Margin="10,0,0,0"/>
<TextBlock Text="{Binding Age}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBlock Text="Name:"/>
<TextBox Text="{Binding SelectedName, Mode=TwoWay}" />
<TextBlock Text="Age:"/>
<TextBox Text="{Binding SelectedAge, Mode=TwoWay}" />
<Button Content="Save Changes" Command="{Binding SaveChangesCommand}" />
</StackPanel>
绑定view至view model简单方法就是设置DataContext:
public MainPage()
  {
  InitializeComponent();
    // simple way to bind the view to the view model
  this.DataContext = new PersonViewModel();
}
效果图:
由于本人翻译水平有限,有些地方欠妥,请园友们不吝指教!
 
                    
                


 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号