MVVM模式在Windows Phone 7上的简单实现

做WPF/Silverlight/Windows Phone 7 这种Markup+Code类型的项目,程序员和Blend的Designer配合起来有时候真是一个“抓狂”,最近研究了MVVM模式后深切体会到这个模式的优越性,我研究不不是很深,希望走过路过的高手多多指教!
先贴个图:
MVVM模式在Windows Phone 7上的简单实现_第1张图片
按照MVVM模式的思想编写的程序应该在思想上抛弃Xaml文件的code behind(即xaml.cs)文件,这样才能让coder和designer各尽其能。coder需要做的就是在designer设计好的xaml文件里对UI控件的值进行Binding,这里应该会用到Command和Behavior。
在我要做到例子里,我需要对UI的Event监听,实现方法将event绑定到Command(这里需要用到一个MVVM Light Toolkit框架,  GalaSoft.MvvmLight, 此下载的文件中包括WPF/Silverlight/WP7的dll版本),而不是用原来的注册event事件(当然这也是MVVM的思想)。关于MVVM Light Toolkit,可以看 这篇文章
接下来我开始展示一个小Demo:
1. 首先看一下我的项目目录及引用的程序集:
MVVM模式在Windows Phone 7上的简单实现_第2张图片
2. view里的ContractsItem, 这个view是展示每个联系人的控件,这个控件很简单,只是简单的绑定了姓名和电话 
View Code
    
    
1 < UserControl x:Class = " TwitterPlatform.Views.ContactsItem "
2 xmlns = " http://schemas.microsoft.com/winfx/2006/xaml/presentation "
3 xmlns:x = " http://schemas.microsoft.com/winfx/2006/xaml "
4 xmlns:d = " http://schemas.microsoft.com/expression/blend/2008 "
5 xmlns:i = " clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity "
6 xmlns:lightToolkit = " clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WP7 "
7 xmlns:mc = " http://schemas.openxmlformats.org/markup-compatibility/2006 "
8 xmlns:vm = " clr-namespace:TwitterPlatform.ViewModel "
9 mc:Ignorable = " d "
10 FontFamily = " {StaticResource PhoneFontFamilyNormal} "
11 FontSize = " {StaticResource PhoneFontSizeNormal} "
12 Foreground = " {StaticResource PhoneForegroundBrush} "
13 Width = " 250 " Height = " 90 " >
14 < UserControl.Resources >
15 < vm:ContactsItemViewModel x:Key = " ContactsItemViewModel " ></ vm:ContactsItemViewModel >
16 </ UserControl.Resources >
17
18 < StackPanel Orientation = " Horizontal " x:Name = " LayoutRoot " Background = " Transparent " >
19 < i:Interaction.Triggers >
20 < i:EventTrigger EventName = " MouseLeftButtonDown " >
21 < lightToolkit:EventToCommand
22 Command = " {Binding ShowMessageBoxCommand, Source={StaticResource ContactsItemViewModel}} "
23 CommandParameter = " {Binding Path=Text, ElementName=NameField} "
24 ></ lightToolkit:EventToCommand >
25 </ i:EventTrigger >
26 </ i:Interaction.Triggers >
27 < Image Width = " 90 " Height = " 90 " Source = " /Images/Person.png " ></ Image >
28 < StackPanel Margin = " 12,0,12,0 " Orientation = " Vertical " >
29 < TextBlock x:Name = " NameField " Text = " {Binding Name, Mode=OneWay} " Margin = " 0,10,0,20 " ></ TextBlock >
30 < TextBlock Text = " {Binding Tel, Mode=OneWay} " ></ TextBlock >
31 </ StackPanel >
32 </ StackPanel >
33 </ UserControl >
3. view里的ContractsList.xaml,这个view负责显示所有的联系人列表,列表的数据加载方式有两种,一种是用command绑定viewmodel的command,另一种是让viewmodel实现IEnumerable接口,这两种方法我都例子里都会有所显示
 
View Code
    
    
1 < UserControl x:Class = " TwitterPlatform.Views.ContactsList "
2 xmlns = " http://schemas.microsoft.com/winfx/2006/xaml/presentation "
3 xmlns:x = " http://schemas.microsoft.com/winfx/2006/xaml "
4 xmlns:d = " http://schemas.microsoft.com/expression/blend/2008 "
5 xmlns:mc = " http://schemas.openxmlformats.org/markup-compatibility/2006 "
6 mc:Ignorable = " d "
7 FontFamily = " {StaticResource PhoneFontFamilyNormal} "
8 FontSize = " {StaticResource PhoneFontSizeNormal} "
9 Foreground = " {StaticResource PhoneForegroundBrush} "
10 xmlns:views = " clr-namespace:TwitterPlatform.Views "
11 xmlns:vm = " clr-namespace:TwitterPlatform.ViewModel "
12 xmlns:i = " clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity "
13 xmlns:lightToolkit = " clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WP7 "
14 xmlns:command = " clr-namespace:TwitterPlatform.Commands "
15 xmlns:toolkit = " clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit "
16 MaxWidth = " 800 " >
17
18 < Grid x:Name = " LayoutRoot " Background = " Transparent " >
19 < Grid.Resources >
20 < DataTemplate x:Key = " ItemTemplate " >
21 <!-- 定义显示每一项数据的数据模板 -->
22 < views:ContactsItem >
23 </ views:ContactsItem >
24 </ DataTemplate >
25 <!-- 定义Xaml对应的ViewModel -->
26 < vm:ContactsListViewModel x:Key = " ContractsListViewModel " ></ vm:ContactsListViewModel >
27 </ Grid.Resources >
28 <!-- 在这里为了简单起见,我直接把ListBox的DataContext设置为ViewModel,
29 ViewModel实现了IEnumerable),这样list的ItemsSource直接binding就可以 -->
30 < ListBox DataContext = " {StaticResource ContractsListViewModel} "
31 ItemsSource = " {Binding} "
32 ItemTemplate = " {StaticResource ItemTemplate} "
33 ScrollViewer.HorizontalScrollBarVisibility = " Disabled "
34 ScrollViewer.VerticalScrollBarVisibility = " Auto " >
35 < ListBox.ItemsPanel >
36 < ItemsPanelTemplate >
37 < toolkit:WrapPanel ></ toolkit:WrapPanel >
38 </ ItemsPanelTemplate >
39 </ ListBox.ItemsPanel >
40 <!-- 对LstBox的loaded事件附件绑定命令,同样,List的数据加载也可以在这个命令excute里进行,然后将ItemsSource绑定到一个集合 -->
41 < i:Interaction.Triggers >
42 < i:EventTrigger EventName = " Loaded " >
43 < lightToolkit:EventToCommand Command = " {Binding LoadedCommand, Mode=OneWay} " ></ lightToolkit:EventToCommand >
44 </ i:EventTrigger >
45 </ i:Interaction.Triggers >
46 </ ListBox >
47 </ Grid >
48   </ UserControl >
 
 4. ViewModel: ContactsListViewModel.cs 类中定义了Command及IEnumerable的方法
 
View Code
    
    
1 using System;
2   using System.Net;
3   using System.Windows;
4   using System.Windows.Controls;
5   using System.Windows.Documents;
6   using System.Windows.Ink;
7   using System.Windows.Input;
8   using System.Windows.Media;
9   using System.Windows.Media.Animation;
10   using System.Windows.Shapes;
11 using System.Collections.Generic;
12 using TwitterPlatform.Model;
13 using System.Collections.ObjectModel;
14 using System.ComponentModel;
15 using TwitterPlatform.Commands;
16
17 namespace TwitterPlatform.ViewModel
18 {
19 public class ContactsListViewModel : IEnumerable < Person >
20 {
21
22 public ContactsListViewModel()
23 {
24 this .LoadedCommand = new ShowMessageCommand();
25 }
26
27 public ShowMessageCommand LoadedCommand { get ; private set ; }
28
29 // GetEnumerator() 加载数据
30 public IEnumerator < Person > GetEnumerator()
31 {
32 var l = new List < Person > (){
33 new Person() { Name = " Michael " , Tel = " 1234567890 " },
34 new Person() { Name = " dali " , Tel = " 1234567890 " },
35 new Person() { Name = " houjun " , Tel = " 1234567890 " },
36 new Person() { Name = " tony " , Tel = " 1234567890 " },
37 new Person() { Name = " jing " , Tel = " 1234567890 " },
38 new Person() { Name = " Joel " , Tel = " 98564875 " }
39 };
40 l.Sort();
41 return l.GetEnumerator();
42 }
43
44 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
45 {
46 return this .GetEnumerator();
47 }
48 }
49 }
 
 
 5. Person类里只定义了Name和Tel两个属性~~
 6. 最后是负责显示list的MainPage 了,在这个page里我用了个Paronama,小戏一下呵呵
 
View Code
    
    
1 <!--
2 主要代码
3 xmlns:controls = " clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls "
4 -->
5 < Grid x:Name = " ContentPanel " Grid.Row = " 1 " Margin = " 12,0,12,0 " >
6 < controls:Panorama Title = " App List " >
7 < controls:Panorama.Background >
8 < ImageBrush ImageSource = " /Images/AppBg.jpg " ></ ImageBrush >
9 </ controls:Panorama.Background >
10 < controls:PanoramaItem Header = " 1. Contacts " Orientation = " Horizontal " >
11 < views:ContactsList ></ views:ContactsList >
12 </ controls:PanoramaItem >
13 < controls:PanoramaItem Header = " 2. FaceBook " >
14
15 </ controls:PanoramaItem >
16 < controls:PanoramaItem Header = " 3. Others " >
17
18 </ controls:PanoramaItem >
19 </ controls:Panorama >
20
21 </ Grid >
22 </ Grid >
23
 
 以上就是这个小小的Demo,简单的实现了MVVM模式,在这个Demo里主要实现了Event To Command,也是MVVM模式经常用到的东西。
如果有时间我会再做一个更加详细的大一点点demo,呵呵
欢迎讨论~~

你可能感兴趣的:(windows,phone)