【Windows Phone 8】使用MVVMLight框架

【簡介】html

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

2.能夠經過Nuget下載MVVLightshell

 

【對比引用文件】express

普通WindowsPhone引用

普通WindowsPhone引用windows

 

使用MVVMLight的WindowsPhone程序引用

使用MVVMLight的WindowsPhone程序引用app

 

Microsoft.Practices.ServiceLocation:依賴注入機制的服務本地化程序集。該程序集可以經過爲依賴注入提供抽象層整合任何適合的依賴注入容器。mvvm

Systems.Windows.interactivity:事件,交互ide

 

【安裝完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

 

【依賴注入】post

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
相關文章
相關標籤/搜索