WP學習筆記(4)MVVM入門 第一部分 INotifyPropertyChanged和ICommand


這一篇到MVVM了,心里很是忐忑,聽說MVVM很長時間了但是一直也沒有真正用過,兩年前做Silverlight那會項目里也沒怎么用,而且那時候還沒有windows phone和win8,所以也沒太在意,悔不當初啊。這一篇我就多用代碼實例說話,少用描述性的文字,以免誤人子弟。

打開前幾篇的代碼,上一篇我們把json轉換成了實體類中的數據並且用彈出框顯示了一下,那么怎么顯示到界面上呢,也許會這么做

1 HttpClient hc = new HttpClient();
2 var task = await hc.GetAsync("http://www.weather.com.cn/data/cityinfo/101010100.html");
3 string result = await task.Content.ReadAsStringAsync();
4 JObject obj = JObject.Parse(result);
5  WeatherModel1 details = (WeatherModel1)JsonConvert.DeserializeObject(obj["weatherinfo"].ToString(), typeof(WeatherModel1));
6 this.DataContext = details;  

在頁面里面這樣

1 <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
2    <Button Content="Button" HorizontalAlignment="Left" Margin="137,103,0,0" VerticalAlignment="Top"  Click="Button_Click"/>
3    <TextBlock HorizontalAlignment="Left" Margin="119,265,0,0" TextWrapping="Wrap" Text="{Binding city}" VerticalAlignment="Top"/>
4 
5 </Grid>

 可以顯示沒問題,但是太丑陋了,要在code-behid里寫很多代碼,搞的顯示和邏輯混亂不堪,刷新一次請求就要重新綁定一次頁面的DataContext,而且這個DataContext要是新的引用(也就是說要重新new一個model出來)顯示上才會刷新。下面我們引入ViewModel
新建一個類叫WeatherViewModel

 1 public class WeatherViewModel : INotifyPropertyChanged
 2     {
 3         //public WeatherViewModel()
 4         //{
 5         //    if (updateCmd == null)
 6         //    {
 7         //        updateCmd = new UpdateCmd(this);
 8         //    }
 9         //}
10         public event PropertyChangedEventHandler PropertyChanged;
11         //public ICommand updateCmd { get; private set; }
12         private string _city;
13         public string city
14         {
15             get
16             {
17                 return _city;
18             }
19             set
20             {
21                 _city = value;
22                 if (PropertyChanged != null)
23                 {
24                     PropertyChanged(this, new PropertyChangedEventArgs("city"));
25                 }
26             }
27         }
28     }

里面有幾行注釋掉的代碼,不用管它那是一會要用的。這個類實現了INotifyPropertyChanged接口,它的作用就是通知UI屬性變更了,UI知道后就會重新調用屬性的get獲取。
下面幾個地方我們這么改,打開app.xaml,找到添加資源的<Application.Resources>標簽,對,就是添加動畫那里。然后在里面添加下面代碼

<my:WeatherViewModel xmlns:my="clr-namespace:PhoneApp3" x:Key="weather"/>

在頁面的頭部添加DataContext="{StaticResource weather}"
把最開始寫在code-behind里的this.DataContext = details改成((WeatherViewModel)this.DataContext).city = details.city;

一樣可以顯示,而且我們只是給屬性重新賦值了。不過codebehind里的代碼還是太多,層次還是不清晰,需要繼續改造。不在code-behind里響應點擊事件,改用command

新建一個類就叫UpdateCmd

 1 public class UpdateCmd : ICommand
 2     {
 3         private WeatherViewModel _weather;
 4         public UpdateCmd(WeatherViewModel weather)
 5         {
 6             _weather = weather;
 7         }
 8         public bool CanExecute(object parameter)
 9         {
10             if (parameter != null)
11             {
12                 CanExecuteChanged(parameter, new EventArgs());
13             }
14             return true;
15 
16             //throw new NotImplementedException();
17         }
18 
19         public event EventHandler CanExecuteChanged;
20 
21         public async void Execute(object parameter)
22         {
23             //System.Windows.MessageBox.Show("a");
24             //throw new NotImplementedException();
25             HttpClient hc = new HttpClient();
26             var task = await hc.GetAsync("http://www.weather.com.cn/data/cityinfo/101010100.html");
27             string result = await task.Content.ReadAsStringAsync();
28             JObject obj = JObject.Parse(result);
29             WeatherModel1 details = (WeatherModel1)JsonConvert.DeserializeObject(obj["weatherinfo"].ToString(), typeof(WeatherModel1));
30             _weather.city = details.city;
31         }
32     }

把WeatherViewModel里注釋的代碼打開。把xaml中button的click換成command

1 <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
2    <Button Content="Button" HorizontalAlignment="Left" Margin="137,103,0,0" VerticalAlignment="Top" Command="{Binding updateCmd}"/>
3    <TextBlock HorizontalAlignment="Left" Margin="119,265,0,0" TextWrapping="Wrap" Text="{Binding city}" VerticalAlignment="Top"/>
4 </Grid>

現在我們可以把code-behind里所有不是自帶的,前幾篇添加的代碼全部注釋掉了。測試一下看看,我們沒有在code-behind里寫一句代碼就實現了數據的顯示。而且我們也完成了view-view model-model分層。上面的代碼里,Command中Excute部分也應該提取出來成為service。
關於INotifyPropertyChanged和ICommand更多的信息感興趣的還是baidu吧,我就不這里獻丑了,網上還是很多的。今天這篇就到這,下一篇簡單應用一下DependencyProperty。

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM