【Windows Phone 8】使用MVVMLight框架

【简介】

1.作者文章:http://www.galasoft.ch/mvvm/

2.可以通过Nuget下载MVVLight

【对比引用文件】

普通WindowsPhone引用

普通WindowsPhone引用

 

使用MVVMLight的WindowsPhone程序引用

使用MVVMLight的WindowsPhone程序引用

 

Microsoft.Practices.ServiceLocation:依赖注入机制的服务本地化程序集。该程序集能够通过为依赖注入提供抽象层整合任何适合的依赖注入容器。

Systems.Windows.interactivity:事件,交互

【安装完MVVMLight之后的文件结构】

<Application x:Class="MVVMLight学习.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
             xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" 
             xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:d1p1="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:vm="clr-namespace:MVVMLight学习.ViewModel"
             d1p1:Ignorable="d" >
    <!--应用程序资源-->
    <Application.Resources>
        <local:LocalizedStrings xmlns:local="clr-namespace:MVVMLight学习" x:Key="LocalizedStrings" />
        <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
    </Application.Resources>
    <Application.ApplicationLifetimeObjects>
        <!--处理应用程序的生存期事件所需的对象-->
        <shell:PhoneApplicationService 
            Launching="Application_Launching" 
            Closing="Application_Closing" 
            Activated="Application_Activated" 
            Deactivated="Application_Deactivated" />
    </Application.ApplicationLifetimeObjects>
</Application>
App.Xaml

【依赖注入】

App.Xaml中使用了ViewModelLocator进行依赖注入,代码如下:

 1 /*
 2   In App.xaml:
 3   <Application.Resources>
 4       <vm:ViewModelLocator xmlns:vm="clr-namespace:MVVMLight.Shell"
 5                            x:Key="Locator" />
 6   </Application.Resources>
 7   
 8   In the View:
 9   DataContext="{Binding Source={StaticResource Locator}, Path=ViewModelName}"
10 
11   You can also use Blend to do all this with the tool's support.
12   See http://www.galasoft.ch/mvvm
13 */
14 
15 using ClientService.Implements;
16 using ClientService.Interfaces;
17 using GalaSoft.MvvmLight.Ioc;
18 using Microsoft.Practices.ServiceLocation;
19 
20 namespace MVVMLight.Shell.ViewModel
21 {
22     /// <summary>
23     /// This class contains static references to all the view models in the
24     /// application and provides an entry point for the bindings.
25     /// </summary>
26     public class ViewModelLocator
27     {
28 
29         #region 构造函数
30 
31         /// <summary>
32         /// Initializes a new instance of the ViewModelLocator class.
33         /// </summary>
34         public ViewModelLocator()
35         {
36             INavigationService navigationService = null;
37 
38             /// 参数是返回值为IServiceLocator的委托
39             ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
40 
41             ////if (ViewModelBase.IsInDesignModeStatic)
42             ////{
43             ////    // Create design time view services and models
44             ////    SimpleIoc.Default.Register<IDataService, DesignDataService>();
45             ////}
46             ////else
47             ////{
48             ////    // Create run time view services and models
49             ////    SimpleIoc.Default.Register<IDataService, DataService>();
50             ////}
51 
52             //这种写法有问题,App.RootFrame会在Application_Launching方法执行完成之后有值
53             //navigationService = new PhoneNavigationService(App.RootFrame);
54             //SimpleIoc.Default.Register<MainViewModel>(() =>
55             //    new MainViewModel(navigationService), false);
56 
57             // 方法执行顺序:
58             // 1.App构造函数
59             // 2.ViewModelLocator构造函数(App.xaml中的资源添加了ViewModelLocator)
60             // 3.App的Application_Launching方法
61             // 4.Navigate方法(App.RootFrame不为空)
62             // 5.取得对应的ViewModel(MainViewModel),执行对应的依赖注入的委托
63             // 正确写法,不立即注入(默认值)
64             // 此处每个ViewModel中的navigationService相同(可考虑改进,适合使用单例模式)
65             SimpleIoc.Default.Register<MainViewModel>(() =>
66                 new MainViewModel(navigationService = new PhoneNavigationService(App.RootFrame)), false);
67 
68             SimpleIoc.Default.Register<Page1ViewModel>(() =>
69                 new Page1ViewModel(navigationService), false);
70         }
71 
72         #endregion
73 
74         public MainViewModel Main
75         {
76             get
77             {
78                 return ServiceLocator.Current.GetInstance<MainViewModel>();
79             }
80         }
81 
82         public Page1ViewModel Page1
83         {
84             get
85             {
86                 return SimpleIoc.Default.GetInstance<Page1ViewModel>();
87             }
88         }
89 
90         public static void Cleanup()
91         {
92             // TODO Clear the ViewModels
93         }
94     }
95 }
ViewModelLocator

【Appbar绑定Command】

使用第三方组件AppBarUtils 命令绑定

<phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar >
            <shell:ApplicationBarIconButton IconUri="/Assets/Images/AppBar/add.png" Text="创建磁贴"/>
            <shell:ApplicationBarIconButton IconUri="/Assets/Images/AppBar/Close.png" Text="删除磁贴">
            </shell:ApplicationBarIconButton>
        </shell:ApplicationBar>
    </phone:PhoneApplicationPage.ApplicationBar>

    <i:Interaction.Behaviors>
        <!--Id与Button的Text对应,Type默认值为Button-->
        <abu:AppBarItemCommand Type="Button" Id="创建磁贴" Command="{Binding CreateTileCommand}"></abu:AppBarItemCommand>
    </i:Interaction.Behaviors>
View Code

【创建动态磁贴ShellTile】

 参考文章:与众不同 windows phone (8) - Tile(磁贴)

        /// <summary>
        /// 创建磁贴
        /// </summary>
        public ICommand CreateTileCommand
        {
            get
            {
                return new RelayCommand(() =>
                {
                    if (ShellTile.ActiveTiles.Where(item => item.NavigationUri.OriginalString == "/Views/Page2.xaml?DeepLink=true").Count() > 0)
                    {
                        MessageBox.Show("已经添加了磁贴");
                        return;
                    }

                    StandardTileData newTile = new StandardTileData
                    {
                        Title = "Page2次要磁贴",
                        //BackgroundImage = new Uri("TileBackgroundBlue.png", UriKind.Relative),
                        Count = 2,
                        BackTitle = "App Back Tile Title",
                        //BackBackgroundImage = new Uri("TileBackgroundGreen.png", UriKind.Relative),
                        BackContent = "App Back Tile Content" + Environment.NewLine + "OK"
                    };

                    //shellTileService.Update(newTile);                    
                    ShellTile.Create(new Uri("/Views/Page2.xaml?DeepLink=true", UriKind.Relative), newTile);
                });
            }
        }

        /// <summary>
        /// 删除磁贴
        /// </summary>
        public ICommand DeleteTileCommand
        {
            get
            {
                return new RelayCommand(() =>
                {
                    var shellTile = ShellTile.ActiveTiles.First(item => item.NavigationUri.OriginalString == "/Views/Page2.xaml?DeepLink=true");
                    shellTile.Delete();
                });
            }
        }    
View Code

【导航Navigate】

使用适配器模式,重新封装本地的一些服务,以提供统一的访问接口(如导航INavigationService)

【快速恢复FastResume】

参考文章:Windows phone 8 Fast Resume 快速恢复浅析(一)

程序清单文件中设置激活方式为Resume

<Tasks>
      <DefaultTask Name="_default" NavigationPage="Views/MainPage.xaml" ActivationPolicy="Resume"/>
    </Tasks>
View Code

在App.xaml.cs文件中,注册RootFrame.Navigating事件,以进行快速恢复的相关处理:

/// <summary>
        /// 快速恢复
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void FastResume(object sender, NavigatingCancelEventArgs e)
        {
            if (e.NavigationMode == NavigationMode.Reset)
            {
                isResume = true;
                return;
            }
            if (isResume && e.NavigationMode == NavigationMode.New)
            {
                isResume = false;
                if (!e.Uri.ToString().Contains("DeepLink=true"))
                {
                    e.Cancel = true;
                }
            }
        }
View Code

【独立存储】

参考:Windows Phone 独立存储之IsolatedStorageSettings

【墓碑恢复】

 Windows Phone 应用程序生命周期

 1 using Microsoft.Phone.Controls;
 2 using System.Windows.Navigation;
 3 
 4 namespace PhoneClient.Adapters.Interfaces
 5 {
 6     public interface INavigationService
 7     {
 8         #region 属性
 9 
10         PhoneApplicationFrame Frame
11         {
12             get;
13         }
14 
15         #endregion
16 
17         #region 事件
18 
19         event NavigatedEventHandler Navigated;
20         event NavigatingCancelEventHandler Navigating;
21 
22         #endregion
23 
24         #region 方法
25 
26         void NavigateTo(string url);
27 
28         #endregion
29     }
30 }
INavigationService.cs
 1 using System;
 2 using System.Windows.Navigation;
 3 
 4 using Microsoft.Phone.Controls;
 5 using PhoneClient.Adapters.Interfaces;
 6 
 7 namespace PhoneClient.Adapters.Implements
 8 {
 9     public class NavigationServiceAdapter : INavigationService
10     {
11         #region 字段
12 
13         private PhoneApplicationFrame frame;
14 
15         #endregion
16 
17         #region 事件
18 
19         public event NavigatedEventHandler Navigated;
20         public event NavigatingCancelEventHandler Navigating;
21 
22         #endregion
23 
24         #region 构造函数
25 
26         public NavigationServiceAdapter(PhoneApplicationFrame frame)
27         {
28             this.frame = frame;
29             this.frame.Navigating += frame_Navigating;
30             this.frame.Navigated += frame_Navigated;
31         }
32 
33         #endregion
34 
35         #region 方法
36 
37         void INavigationService.NavigateTo(string url)
38         {
39             if (this.frame != null)
40             {
41                 this.frame.Navigate(new Uri(url, UriKind.Relative));
42             }
43         }
44 
45         void frame_Navigating(object sender, NavigatingCancelEventArgs e)
46         {
47             if (Navigating != null)
48             {
49                 Navigating(sender, e);
50             }
51         }
52 
53         void frame_Navigated(object sender, NavigationEventArgs e)
54         {
55             if (Navigated != null)
56             {
57                 Navigated(sender, e);
58             }
59         }
60 
61         #endregion
62 
63         PhoneApplicationFrame INavigationService.Frame
64         {
65             get
66             {
67                 return frame;
68             }
69         }
70     }
71 }
NavigationServiceAdapter
 1 using System.Linq;
 2 
 3 using GalaSoft.MvvmLight;
 4 using MVVMLight.Shell.Common.StorageHelper;
 5 using PhoneClient.Adapters.Interfaces;
 6 using System;
 7 
 8 namespace MVVMLight.Shell.ViewModels
 9 {
10     public class ViewModel : ViewModelBase
11     {
12         #region 字段
13 
14         private INavigationService navigationService;
15 
16         private Uri pageUri;
17 
18         #endregion
19 
20         #region 构造方法
21 
22         public ViewModel(INavigationService navigationService, Uri pageUri)
23         {
24             if (navigationService != null)
25             {
26                 this.navigationService = navigationService;
27                 this.pageUri = pageUri;
28                 this.navigationService.Navigating += navigationService_Navigating;
29                 this.navigationService.Navigated += navigationService_Navigated;
30             }
31         }
32 
33         #endregion
34 
35         #region 私有方法
36 
37         private void navigationService_Navigating(object sender, System.Windows.Navigation.NavigatingCancelEventArgs e)
38         {
39             // 保存程序状态
40             if (e.Uri.OriginalString == "app://external/")
41             {
42                 OnPageDeactivation();
43                 IsolatedStorageHelper.SettingSave<bool>("tombstone", true);
44             }
45         }
46 
47         private void navigationService_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
48         {
49             // 墓碑恢复
50             if (e.Uri.OriginalString != "app://external/" && IsolatedStorageHelper.SettingLoad<bool>("tombstone") == true)
51             {
52                 OnPageResumeFromTombstone();
53 
54                 // 所有页面都从墓碑状态恢复之后删除独立存储中的墓碑标识
55                 if (this.navigationService.Frame.BackStack.Count() == 0)
56                 {
57                     IsolatedStorageHelper.SettingRemove("tombstone");
58                 }
59             }
60 
61             // 判断当前导航的页面与ViewModel是否对应
62             if (this.pageUri.OriginalString == e.Uri.OriginalString)
63             {
64                 OnNavigatedTo();
65             }
66         }
67 
68         #endregion
69 
70         #region 方法
71 
72         public virtual void OnPageDeactivation()
73         {
74 
75         }
76 
77         public virtual void OnPageResumeFromTombstone()
78         {
79 
80         }
81 
82         public virtual void OnNavigatedTo()
83         {
84 
85         }
86 
87         #endregion
88 
89     }
90 }
ViewModel
原文地址:https://www.cnblogs.com/fb-boy/p/3533716.html