首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 媒体动画 > CAD教程 >

[分享]在Silverlight中应用MVVM模式,该如何解决

2012-02-15 
[分享]在Silverlight中应用MVVM模式格式一直弄不好,凑合着看吧,原文在此http://blog.sina.com.cn/s/blog_5

[分享]在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
[解决办法]

探讨
请问楼主你会考虑用Prism吗?

热点排行