MVVM

  对于.NET平台的开发人员,托微软的福分我们拥有一种更为强大的模型---MVVM。这应该算是做WPF/Silverlight应用的人必懂的一种结构,WPF/silverlight天生支持数据绑定和命令绑定(不过sl在命令绑定上还比较弱),这就为我们使用MVVM创造了可能。

  

  View是什么呢,纯的View只有xaml或者附带必要的只与View本身相关逻辑代码。ViewModel,你可以把它理解为View具体呈现内容所依赖数据的一个抽象,在MVVM中View与ViewModel总会有一种绑定关系,一旦ViewModel中被绑定的数据发生改变View上的数据就会跟着变,相反也有可能,比如你的账号密码框内容发生变化,关联的ViewModel中的数据就会被框架自动通知到。

  在wpf/silverlight中,绑定是通过xaml语法来完成(虽然你可以选择用c#来写但不符合mvvm的宗旨),并且绑定双方的通知机制是有框架来完成,也就是说一个会xaml和blend的美工只需事先和coder商量下“咱们的xx和xx是在哪个ViewModel上叫XXX的属性的XXX属性……”问题之后就可以各干各的了。那么ViewModel怎么写,咋view中又怎么绑定到viewmodel呢?首先我们谈ViewModel。

  说道ViewModel你需要知道依赖属性和依赖对象的概念,这是wpf/silverlight的基础所以不多说。有两种方式写ViewModel。第一种是自己去实现INotifyPropertyChanged接口,并在属性变化时去调用NotifyPropertyChanged事件。

  为了方便我们定义一个ViewModelBase的抽象基类,然后让其他ViewModel继承这个基类。

  public abstract class ViewModelBase : System.ComponentModel.INotifyPropertyChanged, IDisposable   
    {   
        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;   
        protected void OnPropertyChanged(string propertyName)   
        {   
            if (PropertyChanged != null)   
            {   
      var arg = new System.ComponentModel.PropertyChangedEventArgs(propertyName);   
                PropertyChanged(this, arg);   
            }   
        }   
        public virtual void Dispose()   
        {   
             
        }   
    } 

 

public class DemoViewModel : ViewModelBase     
{          
  #region fields          
  private string _propertyA;          
  #endregion          
  #region presentation properties          
  public string PropertyA          
  {              
    get  { return _propertyA; }              
    set        
       {                  
      if (_propertyA != value)                
      {                      
        _propertyA = value;                   
        base.OnPropertyChanged("PropertyA");             
        }         
       }        
  }
#endregion
}

 

第二种是利用DependencyObject和DependencyProperty。

using System;
using System.Windows;
using System.ComponentModel;

namespace FCClient.AppCode
{
    public class PeopleItemViewModel : DependencyObject, IPeopleItemViewModel
    {
        public PeopleItemViewModel()
        {

        }
        public static readonly DependencyProperty SimpleUserDataProperty 
      = DependencyProperty.Register("SimpleUserData", typeof(SimpleUserData), typeof(PeopleItemViewModel)); public static readonly DependencyProperty RelativeSimpleUserDataProperty
      = DependencyProperty.Register("RelativeSimpleUserData", typeof(ObservableCollection<SimpleUserData>), typeof(PeopleItemViewModel)); public static readonly DependencyProperty AllSimpleUserDataProperty
      = DependencyProperty.Register("AllSimpleUserData", typeof(ObservableCollection<SimpleUserData>), typeof(PeopleItemViewModel)); public SimpleUserData SimpleUserData { get { return (SimpleUserData)base.GetValue(SimpleUserDataProperty); } set { if (!base.CheckAccess()) { Dispatcher.Invoke(new Action( () => { SimpleUserData = value; })); } else base.SetValue(SimpleUserDataProperty, value); } } public ObservableCollection<SimpleUserData> RelativeSimpleUserData { get { return (ObservableCollection<SimpleUserData>)base.GetValue(RelativeSimpleUserDataProperty); } set { if (!base.CheckAccess()) { Dispatcher.Invoke(new Action( () => { RelativeSimpleUserData = value; })); } else { base.SetValue(RelativeSimpleUserDataProperty, value); var collectionView = CollectionViewSource.GetDefaultView(value); collectionView.SortDescriptions.Add(new SortDescription("Distance", ListSortDirection.Ascending)); } } } public ObservableCollection<SimpleUserData> AllSimpleUserData { get { return (ObservableCollection<SimpleUserData>)base.GetValue(AllSimpleUserDataProperty); } set { if (!base.CheckAccess()) { Dispatcher.Invoke(new Action( () => { AllSimpleUserData = value; })); } else { base.SetValue(AllSimpleUserDataProperty, value); var collectionView = CollectionViewSource.GetDefaultView(value); collectionView.SortDescriptions.Add(new SortDescription("Distance", ListSortDirection.Ascending)); } } } } }

 

在View中绑定ViewModel。

为了方便,我们可以在app.xaml中将需要的viewmode放到全局资源字典中。

image

然后再我们的vs视图设计器Properties(中文版显示的是“属性”)页上选择为绑定源设置绑定目标(包括source和path等)以及必要的值转换器等等即可。

image image image

posted on 2016-08-15 19:53  Now,DayBreak  阅读(332)  评论(0编辑  收藏  举报