[分享]在Silverlight中应用MVVM模式
格式一直弄不好,凑合着看吧,原文在此http://blog.sina.com.cn/s/blog_54da57aa0100hlbk.html
最近在做个基于SL的工具,在此谈一下自己对Silverlight的MVVM模式的理解。
MVVM:即Model View ViewModel三层,
个人感觉归根结底MVVM其实就是MVC的一个变种,ViewModel有一个很明显的优点:可降低View->Control的偶合,像 Flash/Silverlight这类RIA应用,在View层中会有不少实现动画效果的代码,而传统的MVC结构,在实现数据更新时,不可避免地要在 View中写很多Control代码,这样的话容易造成结构混乱,
但MVVM基于事件绑定机制,在View层中只要完成绑定即可,View会自动更新Model,Model再通知Control,这样就可大量减少 View层中的Control代码。
下面举个例子说明:
在Silverlight中应用MVVM模式
我们这里有一个可分组的DataGrid控件,现在的需求是: 当用户单击Complete时,实现一些控制操作,如更新某个图表,或更新后台数据库等。
首先:我们需要创建一个Model,此Model继承INotifyPropertyChanged接口,会强制实现 PropertyChangedEventHandler事件即属性更改事件,在Complete的值发生改变时(View->Model)冒出这个事件。
//Model
public class Task :INotifyPropertyChanged
{
public string ProjectName { get; set; }
public string TaskName { get; set; }
public DateTime DueDate { get; set; }
// Private task data.
private bool m_Complete = false;
public bool Complete
{
get { return this.m_Complete; }
set
{
if (value != this.m_Complete)
{
this.m_Complete = value;
NotifyPropertyChanged("Complete");
}
}
}
public string Notes { get; set; }
#region INotifyPropertyChanged 成员
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
然后: 我们需要在Control层中生成绑定数据源,并在数据源上侦听这个属性更改事件(Model->Control),由于多用到泛型集合,所以我们希望在对象被加入集合列表(List)时自动绑定这个事件,因此我们新建一个类以简化这个操作,事实上ObservableCollection中已经包含了PropertyChangedEventHandler事件
,可能是出于性能的考虑,将其设为了protected类型,并且没有进行任何操作,因此我们需要新建一个子类来实现他:
public class ViewModelCollection<T> : ObservableCollection<T>
{
public ViewModelCollection():base() { }
public new void Add(T item)
{
//在添加时自动绑定
((INotifyPropertyChanged)item).PropertyChanged += new PropertyChangedEventHandler(ViewModelCollection_PropertyChanged);
base.Add(item);
}
#region INotifyPropertyChanged 成员
public new event PropertyChangedEventHandler PropertyChanged;
void ViewModelCollection_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
{
//继续向上冒出事件,并传递发生改变的对象
PropertyChanged(sender, new PropertyChangedEventArgs(e.PropertyName));
}
}
#endregion
}
接着: 我们就可以在ViewModel中使用这个泛型集合了,并添加对属性更改事件的侦听。
这里使用的PagedCollectionView对象仅仅是为DataGrid控件提供分组数据源,这也是一个相当强大的类,大家可以查阅相当文档学习他的使用。
//ViewModel
public class ViewModel
{
public PagedCollectionView TaskBinding()
{
// 生成泛型集合数据源。
ViewModelCollection<Task> taskList = new ViewModelCollection<Task>();
for (int i = 1; i <= 14; i++)
{
taskList.Add(new Task()
{
ProjectName = "Project " + ((i % 3) + 1).ToString(),
TaskName = "Task " + i.ToString(),
DueDate = DateTime.Now.AddDays(i),
Complete = (i % 2 == 0),
Notes = "Task " + i.ToString() + " is due on "
+ DateTime.Now.AddDays(i) + ". Lorum ipsum..."
});
}
taskList.PropertyChanged += new PropertyChangedEventHandler(taskList_PropertyChanged);
PagedCollectionView taskListView = new PagedCollectionView(taskList);
// 添加要进行分组的属性
taskListView.GroupDescriptions.Add(new PropertyGroupDescription("ProjectName"));
taskListView.GroupDescriptions.Add(new PropertyGroupDescription("Complete"));
return taskListView;
}
void taskList_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
Task task = (Task)sender;
MessageBox.Show(string.Format("Model Changed: IsComplete={0} PropertyName={1}", task.Complete, e.PropertyName));
//其他一些操作,如更新数据库,图表等
}
}
最后: 我们就可以在View层中进行数据绑定了
public partial class MainPage : UserControl
{
private ViewModel controller;
public MainPage()
{
InitializeComponent();
controller = new ViewModel();
dataGrid1.ItemsSource = controller.TaskBinding();
}
}
最后看一看效果:当用户单击Complete列的选择框时就会触发Control中的控制代码,从而不需要在View中书写额外的代码
[解决办法]
新浪的图片不能被外部调用显示。
支持原创文章。
[解决办法]
顶上去!
[解决办法]
请问楼主你会考虑用Prism吗?
[解决办法]
顶,体会MVVM
[解决办法]