windows phone mvvm 墓碑化處理.

來源:互聯網
上載者:User

我覺的處理墓碑化是一個非常棘手的問題.一旦程式從墓碑化返回當前頁面,當前頁面的所有資料都為空白,會重新調用該頁面的建構函式,建立一個新的頁面,如果這個頁面上沒有使用後台代碼建立的UI的話,還容易一點,如果有使用後台代碼建立的UI,還要需要重新添加UI,然後恢複這些UI的狀態.我覺得這個過程處理起來會很痛苦,我的想法是把需要動態建立UI的部分做成一個UserControl,在UserControl裡面處理建立UI的邏輯.首先在UserControl裡面定義相依性屬性,然後使用資料繫結技術綁定相依性屬性,在ViewModel裡面能過參數設定來控制項UserControl來動態產生UI.如果順利的話就可以使用下面這個庫來處理墓碑化,另外我覺得順利處理墓碑化的前提是程式良好的使用了MVVM模式.

下面我來介紹一下MVVM模式的墓碑化處理方式

首先介紹一個庫在codeplex上面 叫做
MVVM Tombstone for Windows Phone

http://mvvmtombstone.codeplex.com/SourceControl/latest#WindowsPhone.MVVM.Tombstone/WindowsPhone.MVVM.Tombstone/TombstoneAttribute.cs

1 首先使用NuGet來安裝 MVVM Tombstone for windows Phone

2 分別在OnNavigatedFrom和OnNavigatedTo裡面添加如下代碼

protected override void OnNavigatedTo(NavigationEventArgs e){    base.OnNavigatedTo(e);    TombstoneHelper.page_OnNavigatedTo(this, e);} protected override void OnNavigatedFrom(NavigationEventArgs e){    base.OnNavigatedFrom(e);    TombstoneHelper.page_OnNavigatedFrom(this, e);}

3.在App.cs的Application_Activated 方法中添加如下代碼

1
TombstoneHelper.Application_Activated(sender, e);

4.在你需要儲存的屬性上面加上[Tombstone()]

[Tombstone()]public SomeClass MyObject {   get { return _myobject; }    set {      _myobject = value;      RaisePropertyChanged("MyObject");   }}

OK.啦就是這麼簡單.想知道是怎麼實現了,代碼在CodePlex上面.我來介紹一下.代碼主要是利用反射,在程式切到後台時,遍曆當前ViewModel的帶有[Tombstone()]標籤的屬性,將這些屬性的值使用Json.Net進行序列化,然後把序列化的結果儲存到PhoneApplicationPage.State字典中,當程式從後台返回到前台時,遍曆當前ViewModel的帶有[Tombstone()]標籤的屬性,如果這個屬性的值為空白,將儲存在State字典的值讀出來,賦給ViewModel對應的屬性.

下面介紹一下原始碼

1下面這個類就定義了一個屬性標籤,標籤類似於我們使用的注釋,只不過這種標籤是給編譯器看的,在對ViewModel裡面的屬性進行儲存的時候,就是通過判斷對帶有這種標籤的屬性進行儲存.

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]    public class TombstoneAttribute : Attribute    {    }
 

2.下面這個類就是核心類啦.

 internal class ApplicationState    {        static JsonSerializerSettings settings = new JsonSerializerSettings        {            PreserveReferencesHandling = PreserveReferencesHandling.Objects        };                /// <summary>        /// Runs over all the properties in the page's viewmodel and saves the state of those that have the tombstone attribute applied        /// </summary>        static internal void Save(PhoneApplicationPage page)        {            foreach (PropertyInfo tombstoneProperty in GetTombstoneProperties(page.DataContext))            {                string key = GetKey(tombstoneProperty);                                object value = tombstoneProperty.GetValue(page.DataContext, null);                page.State[key] = JsonConvert.SerializeObject(value, Formatting.None, settings);            }        }        /// <summary>        /// Runs over all the properties in the page's viewmodel and restores the state of those that have the tombstone attribute applied and have no value        /// </summary>        static internal void Restore(PhoneApplicationPage page)        {            foreach (PropertyInfo tombstoneProperty in GetTombstoneProperties(page.DataContext))            {                if (tombstoneProperty.GetValue(page.DataContext, null) == null)                {                    string key = GetKey(tombstoneProperty);                    if (page.State.ContainsKey(key))                    {                        tombstoneProperty.SetValue(page.DataContext, JsonConvert.DeserializeObject((string)page.State[key], tombstoneProperty.PropertyType, settings), null);                    }                }            }        }        /// <summary>        /// Defines the key we are saving in the page's state bag        /// </summary>        private static string GetKey(PropertyInfo Prop)        {            return "tshelper.viewmodel." + Prop.Name;        }        /// <summary>        /// Obtains all the propertyinfos that have the TombstoneAttribute applied       /// <param name="ViewModel">The viewmodel to check. This is set to the page's DataContext</param>            private static IEnumerable<PropertyInfo> GetTombstoneProperties(object ViewModel)    {    if (ViewModel != null) {    IEnumerable<PropertyInfo> tsProps = from p in ViewModel.GetType().GetProperties()                                                 where p.GetCustomAttributes(typeof(TombstoneAttribute), false).Length > 0                                                select p;    foreach (PropertyInfo tsProp in tsProps) {    if (!tsProp.CanRead || !tsProp.CanWrite) {    throw new TombstoneException(string.Format("Cannot restore value of property {0}. Make sure the getter and setter are public", tsProp.Name));    }    }    return tsProps;    } else {    return new List<PropertyInfo>();    }    }    }

GetTombstoneProperties返回帶有[Tombstone()]標籤的屬性的集合.

Restore方法用來在墓碑時恢複資料,遍曆帶有Tombstone()標籤的屬性,使用反射從當前的ViewModel中取出屬性的值,如果值為空白,就從State字典中讀出屬性的值,還原序列化後

把值設定到屬性上.

Save方法用來儲存資料,遍曆帶有Tombstone標籤的屬性,將屬性的值序列化後,儲存到State字典中.

3.下面這個類是就是我們所使用的介面

 public sealed class TombstoneHelper    {         private static bool _hasbeentombstoned = false;               public static void Application_Activated(object sender, ActivatedEventArgs e)        {            if (!e.IsApplicationInstancePreserved)            {                _hasbeentombstoned = true;            }        }        private static List<PhoneApplicationPage> restoredpages = new List<PhoneApplicationPage>();        public static void page_OnNavigatedTo(PhoneApplicationPage sender, NavigationEventArgs e)        {            if (sender != null && _hasbeentombstoned && !restoredpages.Contains(sender))            {                restoredpages.Add(sender);                ApplicationState.Restore(sender);            }                              }        public static void page_OnNavigatedFrom(PhoneApplicationPage sender, NavigationEventArgs e)        {            if (!(e.NavigationMode == NavigationMode.Back))            {                if (sender != null)                {                    ApplicationState.Save(sender);                }            }        }    }

當離開當前頁面時架構會調用OnNavigateedFrom方面,在離開當前頁面時分為兩種方式,一種方式是使用者按下Back鍵,這時NavigationMode的值為Back.別一種方式是使用者按下Start鍵,程式進入到後來.當程式切到後台進,是否進入墓碑化是不確定的,所以只要程式一進行到後就對資料進行儲存.

if (!(e.NavigationMode == NavigationMode.Back))      {}

使用這個判斷來排除掉,使用者按下Back鍵的情況.剩下一種當然就是程式切換到後台了.

在page_OnNavigatedTo方法,判斷_hasbeentombstoned是否為true,如果為true,並且已經恢複過的頁面中不包含當前頁面時,恢複資料.(總覺得他設定restoredpages這個List有點多餘,幹啥還要儲存恢複過資料的頁面呢)
Application_Activated這個方法就是設定墓碑化標記.

不知道現在還有沒有處理墓碑化更好的方法呢?

如果程式不對墓碑進行處理的話,我覺得總是不完美,如果哪位朋友有處理墓碑化更好的方式,請您 一定指教.期待您的回複. 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.