最近學習MVVM,至於什么是MVVM我也在這兒不多說了,一是關於它的解釋解釋網上非常多,二是我怕自己講不清,誤導自己沒關系,誤導別人就不好了。。
好了,廢話結束,看是實戰......
這個必應壁紙的demo非常簡單,只有一個頁面,上面有一個Image,一個TextBox和兩個Button控件。
如下圖所示

那么下面吧XAML代碼貼上來
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition Height="auto"/> <RowDefinition Height="auto"/> </Grid.RowDefinitions> <Image Source="{Binding ImageSource}"></Image> <TextBox Grid.Row="1" Text="{Binding Copyright}" IsReadOnly="True"></TextBox> <Grid HorizontalAlignment="Stretch" Grid.Row="2"> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Button Content="上一張" Command="{Binding ButtonCommand}" CommandParameter="上一張" HorizontalAlignment="Center" Grid.Column="0"></Button> <Button Content="下一張" Command="{Binding ButtonCommand}" CommandParameter="下一張" HorizontalAlignment="Center" Grid.Column="1"></Button> </Grid> </Grid> </Grid>
在設計的時候,我是先設計的ViewModel,但是由於設計ViewModel的時候我已經知道必應壁紙的請求參數。
http://cn.bing.com/HPImageArchive.aspx?format=js&idx=idx=0&n=1
有三個查詢參數
format:這個應該是指定返回數據類型,默認設成js不變
idx:如果你想獲取昨天的壁紙,那么這個參數就是1,如果是獲取前天的壁紙,那么這個就是2,經過我測試,他的取值范圍是[-1,15],比較有意思的是,-1應該就是明天的壁紙吧,嘿嘿
n:表示返回數據中包含幾組圖片信息,我設為1
由於我設置的返回格式是json,json的解析我就不貼了,放在demo中,咋們的重點也不是這個。
為了在下面的ViewModel中不出現混亂,我先給出Model的定義。
namespace 必應壁紙實戰.Model { public class BingImageModel {public string copyright { get; set; }//返回圖片的copyright public Uri uri { get; set; } //返回具體圖片的uri public int idx { get; set; } = 0; public int n { get; set; } = 1; } }
ViewModel的設計是我結合了View中的需求設計的。
namespace 必應壁紙實戰.ViewModle { public class BingImageViewModel: ViewModelBase { private string _copyright; public string Copyright { get { return _copyright; } set { _copyright = value; OnPropertyChanged(); } } private BitmapImage _imageSource; public BitmapImage ImageSource { get { return _imageSource; } set { _imageSource = value; OnPropertyChanged(); } } private int index; public int Index { get { return index; } set { if (value <= 0) value = 0; index = value; IndexChanged(); } } public RelayCommand ButtonCommand { get; set; } public BingImageModel Model { get; set; } private void ButtonDown(object param) { string tag = param as string; if (tag != null) { if (tag == "上一張") { Index++; } else { Index--; } } } public BingImageViewModel() { Model = new BingImageModel(); ButtonCommand = new RelayCommand(); ButtonCommand.ExcuteParam = ButtonDown; Index = 0; Copyright = ""; } private async void IndexChanged() { Model = await HttpService.GetBingImageModel(Index); if (Model != null) { ImageSource = await HttpService.GetBingImage(Model); Copyright = Model.copyright; } } } }
我對ViewModel做一個簡單說明
ImageSource和Image空間的Source屬性綁定
Copyright和TextBox的Text屬性綁定
ButtonCommand和兩個Button的Command屬性綁定,並且通過CommandParameter來區別執行的命令
Index對應請求參數idx,在它的值改變后執行IndexChanged來獲取必應壁紙
ButtonDown方法對應ButtonCommand來實現對Index的修改,自增代表前一天,自減代表后一天
Model封裝了獲取壁紙的一些必要信息,結合Service中定義的HttpClinet的helper來實現具體的網絡數據請求。
此外,作為WVVM的必備模式,ViewModel是繼承自ViewModelBase的,用以實現綁定機制。
完成View,ViewModel,和Model后,一定不要忘記在View中對ViewModel的綁定,最簡單就是類似於“this.DataContext=new ViewModel();”了。
到這兒就基本完成了,但感覺寫的有些混亂,我把整個過程中的幾個坑在這兒說說
1.就是關於WVVM,一直沒有弄明白在ViewModel中寫大量的代碼究竟好不好,我還有待研究;
2.用Windows.Web.Http命名空間定義的HttpClient請求圖片數據后,用如下方式實現對一個BitmapImage對象的設置
BitmapImage bitMap = new BitmapImage(); ; var response=await HttpClient.GetAsync(model.uri); var buffer = await response.Content.ReadAsBufferAsync(); byte[] bytes = new byte[buffer.Length]; buffer.CopyTo(bytes); //CopyTo是一個定義在System.Runtime.InteropServices.WindowsRuntime;的對IBuffer的拓展方法,這個一定注意 using (MemoryStream memoryStream = new MemoryStream(bytes)) { var randomstream = memoryStream.AsRandomAccessStream(); await bitMap.SetSourceAsync(randomstream); }
好了,上demo代碼,點擊“我是代碼”下載
