最近面试多次被问及MVVM,虽然看过园子里的教程,毕竟未实际实现过,都回答“只了解,未实践过”。今天终于逼自己去用MVVM重构下这个应用。
这里就不多说MVVM的理论等东西了。需要了解的搜一下园子吧,大把大把的!
这次我选择了MVVM Light框架去实现MVVM。我也没用过其他的框架,也不知道有什么特别的地方或者优势,使用MVVM Light也全听别人说不错。
首先去codeplex下载下来MVVM Light:http://mvvmlight.codeplex.com/ 安装之。安装完成之后在原来的项目上添加引用:
调整项目目录结构:
新建View,ViewModel两个文件夹。把ChannelTile.xaml,MainPage.xaml移动到View文件夹下。在ViewModel文件夹下右键新建类,选择MVVM Light为我们提供的模板:MvvmViewModel(wp7)。
新建一个叫ChannelTileViewModel的类。把原来在ChannelTile.cs文件里的代码移植了一部分过来。
using GalaSoft.MvvmLight; using Microsoft.Xna.Framework.Input.Touch; using Helper; using System; using System.Windows; namespace DBFM7.ViewModel { /// <summary> /// This class contains properties that a View can data bind to. /// <para> /// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel. /// </para> /// <para> /// See http://www.galasoft.ch/mvvm/getstarted /// </para> /// </summary> public class ChannelTileViewModel : ViewModelBase { /// <summary> /// Initializes a new instance of the ChannelTileViewModel class. /// </summary> public ChannelTileViewModel() { TouchPanel.EnabledGestures = GestureType.Tap | GestureType.HorizontalDrag; if (!PlayListHelper.IsInited) { PlayListHelper.InitChannelComplete += new Action(PlayListHelper_InitChannelComplete); PlayListHelper.InitChannel();//初始化播放列表 } else this.IsShowGoBtn = Visibility.Visible; } private string _Title="频道正在初始化..."; /// <summary> /// 标题 /// </summary> public string Title { get { return _Title; } set { this._Title = value; this.RaisePropertyChanged("Title"); } } private Visibility _IsShowGoBtn=Visibility.Collapsed; /// <summary> /// 是否显示右边的箭头 /// </summary> public Visibility IsShowGoBtn { get { return this._IsShowGoBtn; } set { this._IsShowGoBtn = value; this.RaisePropertyChanged("IsShowGoBtn"); } } /// <summary> /// 初始化tile的image跟title /// </summary> protected void PlayListHelper_InitChannelComplete() { this.Title = "请选择一个你喜欢的频道"; } } }
这个类继承ViewModelBase,它已经帮我们实现了INotifyPropertyChanged接口,所以简化了实现ViewModelBase的步骤。我们只要定义一个属性,然后在set方法里调用RaisePropertyChanged()方法就实现了依赖属性。
然后在项目目录下新建一个MvvmViewModelLocator,还是使用MVVM Light的模板:
using GalaSoft.MvvmLight; using GalaSoft.MvvmLight.Ioc; using Microsoft.Practices.ServiceLocation; using DBFM7.ViewModel; namespace DBFM7 { /// <summary> /// This class contains static references to all the view models in the /// application and provides an entry point for the bindings. /// <para> /// Use the <strong>mvvmlocatorproperty</strong> snippet to add ViewModels /// to this locator. /// </para> /// <para> /// See http://www.galasoft.ch/mvvm/getstarted /// </para> /// </summary> public class MvvmViewModelLocator { static MvvmViewModelLocator() { ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); if (ViewModelBase.IsInDesignModeStatic) { // SimpleIoc.Default.Register<IDataService, Design.DesignDataService>(); } else { // SimpleIoc.Default.Register<IDataService, DataService>(); } SimpleIoc.Default.Register<ChannelTileViewModel>(); } /// <summary> /// Gets the Main property. /// </summary> [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "This non-static member is needed for data binding purposes.")] public ChannelTileViewModel ChannelTile { get { return ServiceLocator.Current.GetInstance<ChannelTileViewModel>(); } } } } 把生成的MainViewModel替换成ChannelTileViewModel。
在APP.Xaml添加一个静态资源:
<Application.Resources> <vm:MvvmViewModelLocator xmlns:vm="clr-namespace:DBFM7" x:Key="Locator" /> </Application.Resources>
把ChannelTileViewModel跟ChannelTile.xaml绑定起来。
<phone:PhoneApplicationPage xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit" x:Class="DBFM7.View.ChannelTile" 。。。。。。。。。。。。
<!--LayoutRoot is the root grid where all page content is placed--> <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!--TitlePanel contains the name of the application and page title--> <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,0"> <TextBlock x:Name="ApplicationTitle" Text="DB.FM 7" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock HorizontalAlignment="Center" x:Name="PageTitle" Margin="0,40,0,0" FontSize="22"/> </StackPanel>
。。。。。。。。。。。。。。。。。。
<Image Grid.Column="2" VerticalAlignment="Top" Margin="0,12,0,0" Width="48" Height="48" Source="..\ICON\RightGo.png" x:Name="imgGo" Tap="imgGo_Tap" />