上一節完成了SetPage的布局和數據綁定。這一節就要做設置頁面和主頁面的交互了。
我們在主頁面點擊設置按鈕的時候,是不是應該給設置頁面傳一個參數?比如城市名稱?還有在設置頁面ListPicker應該選擇的是當前選擇的地區,不然每次都是兩個北京就顯得很不友好了。
我們在SetPage怎么知道是當前選擇的地區呢。給另一個界面傳參數可以考慮用Uri的方法,比如/SetPage.xaml?cityname="長安" ,然后從URi里面把參數取出來,NavigationContext.QueryString["cityname"]取出來值。但是這里我不考慮這方法,因為我的選擇城市只有一個,直接保存到Isolatedstorage就行了。在SetPage里面再取出來。不過大部分程序還得用傳參數形式,畢竟不能寫多個頁面,要一個頁面多用嘛。舉個簡單的例子,QQ的聊天框,總不能給每個好友都自定義一個 吧。
還有就是天氣更新問題,從SetPage設置后重新回到MainPage,天氣是否需要更新呢,這個也是個問題,如果人家沒改選擇也點擊保存后回到MainPage,更新是否太浪費了。在這個流量還是很貴的時代。還有就是每次啟動程序進入的時候都要更新么,畢竟服務器那頭數據沒有更新,這頭客戶端去請求,返回的數據和原來的一樣,又是浪費流量浪費電量。window phone其實有一個叫推送的東西,這個東西簡單來說就是服務端有更新,就通過推送通知客戶端更新,這樣,即省了流量也省了電量。但是在這里就不展示推送的編寫過程了。
所以,我自己制定的規則是:保存上一次更新的天氣數據。然后從SetPage回來判斷下城市是否相同,不同更新,更新時間是否超過3小時,超過更新。
那么就開始做吧。
先在SetPage頁面的ApplicationBar添加一個IconButton。圖標用的是Dark文件夾下的appbar.save.rest.png。復制到工程的Icons目錄。並且修改生成操作屬性為內容。這不懂操作的參考上一節。並且添加click事件。
<shell:ApplicationBarIconButton IconUri="/Icons/appbar.save.rest.png" Text="保存" Click="ApplicationBarIconButton_Click"/>
先添加一個類來保存選擇的城市信息。工程---右鍵---添加---類---命名為SelectedCity.cs---添加。
在SelectedCity.cs上,首先添加命名空間
using System.IO.IsolatedStorage;
這里附上SelectedCity.cs完整代碼:
using System; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.IO.IsolatedStorage; namespace WeatherForecast { /// <summary> /// 用來保存設置城市信息 /// </summary> public class SelectedCity { private string _province; public string Province { get { return _province; } set { _province = value; } } private string _citycode; public string CityCode { get { return _citycode; } set { _citycode = value; } } private string _cityname; public string Cityname { get { return _cityname; } set { _cityname = value; } } #region 往Isolate的storageSettings保存和取回設置的城市信息 public static void SaveIsolated(SelectedCity sc) { IsolatedStorageSettings iss = IsolatedStorageSettings.ApplicationSettings; iss["SelectedCity"] = sc; } public static SelectedCity GetIsolated() { IsolatedStorageSettings iss = IsolatedStorageSettings.ApplicationSettings; SelectedCity sc = null; SelectedCity temp = null; if (iss.TryGetValue("SelectedCity", out temp))//取值的時候要先判斷是否存在 sc = temp; return sc; } #endregion } }
接下來,我們要編寫的是保存按鈕的事件:
/// <summary> /// 保存設置並且返回MainPage /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void ApplicationBarIconButton_Click(object sender, EventArgs e) { string cityname = citylp.SelectedItem.ToString(); string prov = provincelp.SelectedItem.ToString(); string citycode = String.Empty; //從數據庫取出城市的代碼 using (var db = new CityDataContext(CityDataContext.connectionString)) { var queries = from c in db.CityInfos where (c.Province == prov && c.CityName == cityname) select c; citycode = queries.First().CityCode; } SelectedCity.SaveIsolated(new SelectedCity { CityCode = citycode,Cityname = cityname,Province = prov}); NavigationService.Navigate(new Uri("/WeatherForecast;component/MainPage.xaml",UriKind.Relative)); }
然后到WeatherInfo.cs里面添加如下成員,並且添加命名空間。
public DateTime UpdateTime { get; set; } #region 保存天氣信息到Isolatedstorage public static void SaveIsolated(WeatherInfo w) { IsolatedStorageSettings iss = IsolatedStorageSettings.ApplicationSettings; iss["WeatherInfo"] = w; } public static WeatherInfo GetIsolated() { IsolatedStorageSettings iss = IsolatedStorageSettings.ApplicationSettings; WeatherInfo w = null; WeatherInfo temp = null; if (iss.TryGetValue("WeatherInfo", out temp))//取值先判斷值是否存在 w = temp; return w; } #endregion
接下來,要做的就是保存后,MainPage頁面的天氣更新問題。
我們要做的是在更新的時候先判斷是否需要更新,判斷條件在前面說過了,如果不需要更新還得把Ui更新。大概方向如此,具體代碼經過一些整合修改,貼出來有改動部分:
SelectedCity sc = null; string uriFormat = "http://m.weather.com.cn/data/{0}.html"; private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e) { UpdateWeather(); } /// <summary> /// 判斷是否需要更新天氣,需要更新為True /// </summary> /// <returns></returns> bool isUpdated() { sc = SelectedCity.GetIsolated(); weather = WeatherInfo.GetIsolated(); if (sc == null)//如果從IsolatedStorage里面取到的為空,就是沒有設置地區。則設置默認為北京 { sc = new SelectedCity(); sc.CityCode = "101010100"; sc.Cityname = "北京"; sc.Province = "北京"; return true; } if (weather == null)//如果從來沒有更新過天氣。就更新 { return true; } if (weather.UpdateTime == null || !sc.Cityname.Equals(weather.city))//如果更改了地區,或者沒有更新過天氣。更新 return true; TimeSpan ts1 = new TimeSpan(weather.UpdateTime.Ticks); TimeSpan ts2 = new TimeSpan(DateTime.Now.Ticks); TimeSpan ts = ts1.Subtract(ts2).Duration(); if (ts.Hours >= 3)//如果更新時間差超過3小時,更新 return true; return false; } void UpdateWeather() { if (!isUpdated()) { UpdateUI(); return; } string uri = String.Format(uriFormat, sc.CityCode); WebClient wb = new WebClient();//用WebClient獲取天氣。 wb.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wb_DownloadStringCompleted);//添加Download完成事件 wb.DownloadStringAsync(new Uri(uri, UriKind.Absolute));//開始異步Download } /// <summary> /// 下載完成后的處理事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void wb_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) { //判斷是否下載成功 if (e.Result.Length <= 0 || e.Error != null || e.Cancelled) { MessageBox.Show("獲取天氣預報失敗!"); return; } SelectedCity.SaveIsolated(sc);//保存更新好的城市信息 JObject json = JObject.Parse(e.Result);//用Jobject解析json數據 weather = new WeatherInfo { city = (string)json["weatherinfo"]["city"], cityid = (string)json["weatherinfo"]["cityid"], date_y = (string)json["weatherinfo"]["date_y"], week = (string)json["weatherinfo"]["week"], info = (string)json["weatherinfo"]["index48_d"], wind1 = (string)json["weatherinfo"]["wind1"], temp1 = (string)json["weatherinfo"]["temp1"], temp2 = (string)json["weatherinfo"]["temp2"], temp3 = (string)json["weatherinfo"]["temp3"], temp4 = (string)json["weatherinfo"]["temp4"], temp5 = (string)json["weatherinfo"]["temp5"], weather1 = (string)json["weatherinfo"]["weather1"], weather2 = (string)json["weatherinfo"]["weather2"], weather3 = (string)json["weatherinfo"]["weather3"], weather4 = (string)json["weatherinfo"]["weather4"], weather5 = (string)json["weatherinfo"]["weather5"] }; weather.UpdateTime = DateTime.Now; WeatherInfo.SaveIsolated(weather);//保存更新好的天氣信息 UpdateUI(); }
下面要做的是進入SetPage的時候進行數據綁定顯示,要顯示為用戶已經選擇的城市信息。
方式是先設置省份的SelectedIndex然后,在SelectionChange事件選擇地區
修改或增加的代碼如下:
SelectedCity sc = null; private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e) { ProvLpDataBind(); } void ProvLpDataBind() { //給省份的listpicker綁定數據 provincelp.ItemsSource = prov; sc = SelectedCity.GetIsolated(); if (sc == null) return; int i; for (i = 0; i < prov.Length; i++) { if (prov[i] == sc.Province) break; } provincelp.SelectedIndex = i; } private void provincelp_SelectionChanged(object sender, SelectionChangedEventArgs e) { ListPicker lp = sender as ListPicker; string p = lp.SelectedItem.ToString(); ProvSelectedChanged(p); } /// <summary> /// 由當前選擇的省份給city的ListPicker綁定數據,並返回該省份所以城市名單 /// </summary> /// <returns></returns> List<String> cityDataBind(String prov) { IList<CityInfoTable> list = null; using (CityDataContext db = new CityDataContext(CityDataContext.connectionString)) { IQueryable<CityInfoTable> queries = from c in db.CityInfos where c.Province == prov select c; list = queries.ToList(); } List<String> l = new List<string>(); foreach (var item in list) { l.Add(item.CityName); } citylp.ItemsSource = l; return l; } /// <summary> /// 省份改變,地區綁定,並選擇原來設置的地區 /// </summary> /// <param name="prov"></param> void ProvSelectedChanged(String prov) { List<String> l = cityDataBind(prov); if (sc != null && sc.Province == prov) { int i = l.IndexOf(sc.Cityname); citylp.SelectedIndex = i; } }
運行,成功!這節都是代碼。。。。
這節工程下載:chapter6