• 【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
  • 相关阅读:
    「2017 山东三轮集训 Day1」Flair
    Luogu P4321 随机漫游
    「WC2018」通道
    「CTSC2018」暴力写挂
    关于二项式相乘
    BZOJ #3625 CF #438E 小朋友和二叉树
    GIS可视化
    微信小程序Promise对象
    SQL Server-执行计划教会我如何创建索引
    IIS+NGINX 负载web服务器
  • 原文地址:https://www.cnblogs.com/fb-boy/p/3533716.html
Copyright © 2020-2023  润新知