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

做WPF/Silverlight/Windows Phone 7 这种Markup+Code类型的项目,程序员和Blend的Designer配合起来有时候真是一个“抓狂”,最近研究了MVVM模式后深切体会到这个模式的优越性,我研究不不是很深,希望走过路过的高手多多指教!
先贴个图:
按照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. 首先看一下我的项目目录及引用的程序集:
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,呵呵
欢迎讨论~~
posted @ 2011-03-02 15:18  vvGO  阅读(976)  评论(2编辑  收藏  举报