寫了篇MVVM小記http://www.cnblogs.com/whosedream/p/mvvmnote1.html,說好要寫點MVVMLight的東西,所以接着寫,以便和大家共勉。
我假設你已經有了MVVM的一些概念,那么我們就單刀直入了,怎樣基於MVVMLight 來建項目呢?其實很簡單,首先我們需要下載MVVMLight,然后安裝,完了你會看到
Binaries里有各個版本的程序集
這里我用到了silverlight4的程序集
不過你安裝了模板的話,新建模板項目,那么上面這些程序集就不用你手動去添加了,我用的是VS2012,所以安裝了下面的第二個模板MvvmLight.VS2012.vsix
現在可以新建項目了,在新建項目silverlight選項里你會多看見2個選項
我用的是SL4那么我就選擇第一個新建
我們可以看到一個大體的架子幫你搭出來了,按F5運行,會看到
恭喜你的第一個MVVMLight應用完成了!!!讓我們看看都寫了些什么。
找到程序的入口App
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="MvvmLightTest.App" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:vm="clr-namespace:MvvmLightTest.ViewModel" mc:Ignorable="d"> <Application.Resources> <!--Global View Model Locator--> <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" /> </Application.Resources> </Application>
我們看到添加了個應用程序資源ViewModelLocator,這是干什么用的呢,下面再說,看看App.cs里寫了些什么
private void Application_Startup(object sender, StartupEventArgs e) { RootVisual = new MainPage(); DispatcherHelper.Initialize(); } private void Application_Exit(object sender, EventArgs e) { ViewModelLocator.Cleanup(); }
和以前的代碼相比,在程序退出里我們又看到了ViewModelLocator,看來這東西是貫穿我們應用程序始終的,待會再說。我們還發現在啟動里多了個 DispatcherHelper.Initialize(),這是初始化什么的呢?
... public static void Initialize() { if (UIDispatcher == null) { UIDispatcher = Deployment.Current.Dispatcher; } } public static Dispatcher UIDispatcher { get; private set; } ...
看到了嗎?它會獲取當前應用程序的Dispatcher,Dispatcher是干什么用的?跨線程操作的時候你就會用到。
好了我們的程序RootVisual已經置了MainPage了,看看MainPage有什么
<UserControl x:Class="MvvmLightTest.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:ignore="http://www.ignore.com" mc:Ignorable="d ignore" Height="300" Width="300" DataContext="{Binding Main, Source={StaticResource Locator}}"> <UserControl.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="Skins/MainSkin.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </UserControl.Resources> <Grid x:Name="LayoutRoot"> <TextBlock FontSize="36" FontWeight="Bold" Foreground="Purple" Text="{Binding WelcomeTitle}" VerticalAlignment="Center" HorizontalAlignment="Center" TextWrapping="Wrap" /> </Grid> </UserControl>
是不是還奇怪App里怎么MainPage沒有對DataContext進行賦值,原來在這里
DataContext="{Binding Main, Source={StaticResource Locator}}"
這里Locator是不是很熟悉,啊~對了,就是App的資源文件里添加的東西。現在我們來看看到底ViewModelLocator扮演着何方神聖。
public class ViewModelLocator { static ViewModelLocator() { ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); if (ViewModelBase.IsInDesignModeStatic) { SimpleIoc.Default.Register<IDataService, Design.DesignDataService>(); } else { SimpleIoc.Default.Register<IDataService, DataService>(); } SimpleIoc.Default.Register<MainViewModel>(); } /// <summary> /// Gets the Main property. /// </summary> public MainViewModel Main { get { return ServiceLocator.Current.GetInstance<MainViewModel>(); } } /// <summary> /// Cleans up all the resources. /// </summary> public static void Cleanup() { } }
ServiceLocator 和 SimpleIoc 這兩個東西比較陌生,看ServiceLocator的注釋
This class provides the ambient container for this application. If your framework
defines such an ambient container, use ServiceLocator.Current to get it.
該類為應用程序提供了一個容器,如果你的框架定義了這么一個容器,那么你可以用ServiceLocator.Current來獲取。
既然是個容器,那么是干嘛的呢?繼續看代碼,ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);為這個容器置一個委托SimpleIoc.Default,可能看到IOC,馬上就想到了控制反轉,依賴注入。對~SimpleIoc就是MVVMLight實現的一個IOC容器,再看SimpleIoc.Default.Register方法,你就明白原來是往容器里塞東西(接口實現,類)。
有放就有取
public MainViewModel Main { get { return ServiceLocator.Current.GetInstance<MainViewModel>(); } }
這也是頁面綁定的屬性
到現在我們只看到了個ViewModel的屬性,嗯,看看ViewModel是怎樣的
public class MainViewModel : ViewModelBase { private readonly IDataService _dataService; /// <summary> /// The <see cref="WelcomeTitle" /> property's name. /// </summary> public const string WelcomeTitlePropertyName = "WelcomeTitle"; private string _welcomeTitle = string.Empty; /// <summary> /// Gets the WelcomeTitle property. /// Changes to that property's value raise the PropertyChanged event. /// </summary> public string WelcomeTitle { get { return _welcomeTitle; } set { if (_welcomeTitle == value) { return; } _welcomeTitle = value; RaisePropertyChanged(WelcomeTitlePropertyName); } } /// <summary> /// Initializes a new instance of the MainViewModel class. /// </summary> public MainViewModel(IDataService dataService) { _dataService = dataService; _dataService.GetData( (item, error) => { if (error != null) { // Report error here return; } WelcomeTitle = item.Title; }); } ////public override void Cleanup() ////{ //// // Clean up if needed //// base.Cleanup(); ////} }
它繼承了ViewModelBase,其實它還是實現了 INotifyPropertyChanged, System.ComponentModel.INotifyPropertyChanging這些個東西
是不是沒有發現Model,呵呵,WelcomeTitle 不就是Model嗎?
今天到此為止,源碼下載 如果對您有所幫助的話就頂個吧。