[分享]在Silverlight中应用MVVM模式

c2u 2010-04-10 10:53:46
格式一直弄不好,凑合着看吧,原文在此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中书写额外的代码
...全文
390 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
jv9 2010-06-09
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 namhyuk 的回复:]
请问楼主你会考虑用Prism吗?
[/Quote]

Prism框架用在Silverlight太大了,有点杀鸡用牛刀的感觉,增加了开发和维护的难度,降低了效率。不推荐使用。
namhyuk 2010-06-08
  • 打赏
  • 举报
回复
请问楼主你会考虑用Prism吗?
Sunpire 2010-06-08
  • 打赏
  • 举报
回复
顶,体会MVVM
huo789 2010-04-15
  • 打赏
  • 举报
回复
顶上去!
jv9 2010-04-11
  • 打赏
  • 举报
回复
新浪的图片不能被外部调用显示。
支持原创文章。

8,742

社区成员

发帖
与我相关
我的任务
社区描述
WPF/Silverlight相关讨论
社区管理员
  • WPF/Silverlight社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧