今天小梦继续和大家分享一下MVVM之一个简单的课程表应用.其运行效果如图.没有设计UI,大家不要嫌弃.讲了记事本之后还要在讲这个课程表应用,有俩个原因.一个原因是让大家清楚ViewModel不一定是一个页面对应一个ViewModel,也可以是页面的一部分对应一个ViewModel.还有就是让大家熟悉下JSON的序列化和反序列化.所以这个课程表是使用json存储数据的.
这个课程表和上一篇的记事本本质是一样的.所以小梦重点强调一下我们需要注意的细节和易错的地方:
public class CourseTimetableColumnViewModel:ModelBase { public DayOfWeek Day { get; private set; }//星期 public ObservableCollectionCourses { get; private set; }//课程 public CourseTimetableColumnViewModel(DayOfWeek day) { Day = day; Courses = new ObservableCollection ( from course in JsonCourseStore.Current.Courses where course.Day == Day orderby course.StartTime select course ); } }
那么整个课程表页面对应的ViewMode: CourseTimetableViewModel呢?很简单,它只需要一次建立周一到周日七个CourseTimetableColumnViewModel即可.这样CourseTimetableViewModel的内容就有了.根据我们之前记事本应用的经验.我们还需要增加课表,删除课表,修改课表3个命令.这样基本就可以算完了.但是为了更好的人性化,比如我们希望用户每次打开课表显示的都是今天的课程,那么我们应该怎么办呢:我们课表使用的是Pivot控件,而Pivot控件有一个SelectedIndex属性,表示的是当前选中的是哪一项.所以我们还需要在CourseTimetableViewModel再添加一个SelectCourseIndex属性,用来确保用户首次打开课表显示的是今天的课表.CourseTimetableViewModel完整代码如下:
using Schedule.Command; using Schedule.Common; using Schedule.Models; using Schedule.Service; using Schedule.Views; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Schedule.ViewModels { public class CourseTimetableViewModel:ModelBase { public ListCourseListViewModels { get; private set; } private int selectCourseIndex; public int SelectCourseIndex { get { return selectCourseIndex; } set { this.SetProperty(ref this.selectCourseIndex, value); } } public DelegateCommand AddCommand { get; set; } public DelegateCommand DeleteCommand { get; set; } public DelegateCommand EditCommand { get; set; } public CourseTimetableViewModel() { CourseListViewModels = new List (); for (int i = 0; i < 7; i++) { CourseListViewModels.Add(new CourseTimetableColumnViewModel((DayOfWeek)i)); } selectCourseIndex = (int)DateTime.Today.DayOfWeek; AddCommand = new DelegateCommand(Add); DeleteCommand = new DelegateCommand(Delete); EditCommand = new DelegateCommand(Edit); } private void Add() { DayOfWeek day = CourseListViewModels[selectCourseIndex].Day; NavigationHelp.NavigateTo(typeof(NewOrEditCourse),day); } private void Delete(Object paramater) { Guid id = (Guid)paramater; var course = JsonCourseStore.Current.Courses.FirstOrDefault ( c => c.ID == id ); CourseListViewModels[SelectCourseIndex].Courses.Remove(course); JsonCourseStore.Current.Delete(course); } private void Edit(Object paramater) { Guid id = (Guid)paramater; NavigationHelp.NavigateTo(typeof(NewOrEditCourse),id); } } }
这样课表页面的ViewModel就介绍完了.下面再说一下json的序列化和反序列化.这个在林老师的<深入浅出windows phone 8.1>中有说明.我就直接上代码了:json的序列化和反序列就是那几行代码,一般只需要改变一下数据的类型就可以了.
using Schedule.Models; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Runtime.Serialization.Json; using System.Text; using System.Threading.Tasks; using Windows.Storage; using System.IO; namespace Schedule.Service { public class JsonCourseStore { StorageFolder localFolder = ApplicationData.Current.LocalFolder; private static string JsonCourseName = "course.json"; public ObservableCollectionCourses//所有课程 { get; set; } private static JsonCourseStore jsonCourseStore;//单例模式() public static JsonCourseStore Current { get { if (jsonCourseStore == null) { jsonCourseStore = new JsonCourseStore(); } return jsonCourseStore; } } private JsonCourseStore() { } public async void Getdata() { await LoadCourseFromStorage(); } public async Task Commit()//保存课表 { var jsonSerializer = new DataContractJsonSerializer(typeof(ObservableCollection )); using (var stream = await localFolder.OpenStreamForWriteAsync(JsonCourseName, CreationCollisionOption.ReplaceExisting)) { jsonSerializer.WriteObject(stream, Courses); } } private async Task LoadCourseFromStorage()//读取课表 { IReadOnlyList files = await localFolder.GetFilesAsync(); bool isExist = files.Any(file => file.Name == JsonCourseName); if (isExist) { using (var stream = await localFolder.OpenStreamForReadAsync(JsonCourseName)) { var jsonSerializer = new DataContractJsonSerializer(typeof(ObservableCollection )); Courses = (ObservableCollection )jsonSerializer.ReadObject(stream); } } else { Courses = new ObservableCollection (); } } public async void Add(Course Note) { Courses.Add(Note); await Commit(); } public async void Delete(Course Note) { Courses.Remove(Note); await Commit(); } public async void Modify(Course data) { var oldData = from n in Courses where n.ID == data.ID select n; Course course = oldData.FirstOrDefault(); Courses.Remove(course); Courses.Add(data); await Commit(); } } }
最后还有俩点大家需要注意:
下面的代码和记事本应用的区别就不大了,大家直接看源码吧.