Prism应用开发(五)——MVVM模式关键技术

来源:互联网 发布:微信报码编码软件 编辑:程序博客网 时间:2024/06/06 00:14

一、Data Binding

Data Binding在MVVM模式中起到了重要的作用,WPF提供了强大的数据绑定功能,因此在设计view和model时应该充分利用这些能力,这意味着你必须实现正确的接口。

1)WPF支持one-way binding和two-way binding,two-way binding会将用户对界面数据的修改自动更新到底层数据对象。

2)为了将view model或者model中的数据更新通知到view,需要实现INotifyPropertyChanged接口或者INotifyCollectionChanged接口(如果model是一个集合)。

3)此外,ICollectionView接口在view和view model/model底层集合对象之间提供了排序、过滤、分组以及选择元素的跟踪操作。WPF的ListCollectionView实现了ICollectionView接口。

二、Commands

在WPF中,用户通过UI进行的操作被定义为Commands。Commands为操作和UI上的控件进行绑定提供了一种便利的方式。

WPF的一些控件提供了Command属性,这个属性可以绑定到viewModel中实现了ICommand接口的对象,例如:

public class QuestionnaireViewModel{public QuestionnaireViewModel(){this.SubmitCommand = new DelegateCommand<object>(this.OnSubmit, this.CanSubmit );}public ICommand SubmitCommand { get; private set; }private void OnSubmit(object arg) {...}private bool CanSubmit(object arg) { return true; }}
<Button Command="{Binding Path=SubmitCommand}" CommandParameter="SubmitOrder"/>
<Button Content="Submit" IsEnabled="{Binding CanSubmit}"><i:Interaction.Triggers><i:EventTrigger EventName="Click"><i:InvokeCommandAction Command="{Binding SubmitCommand}"/></i:EventTrigger></i:Interaction.Triggers></Button>

三、数据验证

在MVVM模式中,数据验证可以通过在view model / model实现IDataErrorInfo接口和INotifyDataErrorInfo接口来实现,这些接口允许view model / model对一个或多个属性进行数据验证,并且向view返回errir message。

IDataErrorInfo接口提供了基本的数据验证和错误报告的功能,它包含两个属性,一个索引器属性(索引器使用属性名作为参数)和一个Error属性。索引器属性根据传递的属性名返回错误消息,如果返回值为Empty或者null,表示属性change合法,Error属性为整个对象提供error message,但是现在的WPF和Silverlight引擎都没有使用这个属性。

IDataError的索引器属性将会在第一次数据绑定或者属性的每次改变被调用,因为索引器属性在每个属性发生改变的时候都会被调用,所以要保证这个数据验证函数要尽可能的高效。

<TextBoxText="{Binding Path=CurrentEmployee.Name, Mode=TwoWay, ValidatesOnDataErrors=True,NotifyOnValidationError=True }"/>
 public class Agent : NotificationObject, IDataErrorInfo    {         /// <summary>        /// Name of Agent        /// </summary>        [DisplayOrder(1)]        [DisplayName("Agent Name")]        public string DisplayName        {            get            {                return displayName;            }            set            {                if (displayName != value)                {                    displayName = value;                    this.isSelfChanged = true;                    RaisePropertyChanged<string>(() => this.DisplayName);                    RaisePropertyChanged<string>(() => this.Error);                }            }        }        /// <summary>        /// the address client can connect to the agent        /// </summary>        [DisplayOrder(2)]        [DisplayName("EndPoint Address")]        public string Address        {            get            {                return address;            }            set            {                address = value;                this.isSelfChanged = true;                RaisePropertyChanged<string>(() => this.Address);                RaisePropertyChanged<string>(() => this.Error);            }        }            #region IDataErrorInfo Members        string IDataErrorInfo.Error        {            get { throw new NotImplementedException(); }        }        string IDataErrorInfo.this[string columnName]        {            get            {                if (!string.IsNullOrEmpty(columnName))                {                    Error = string.IsNullOrEmpty(Error) ? Error : (Error + Environment.NewLine);                    switch (columnName)                    {                        case "DisplayName":                            if (string.IsNullOrEmpty(DisplayName))                                return "Display name is required.";                        case "Address":                            if (string.IsNullOrEmpty(Address))                                return "Address is required.";                        default:                            return string.Empty;                    }                }                return string.Empty;            }        }        #endregion         } 
INotifyDataErrorInfo接口比IDataErrorInfo更灵活,它支持一个属性的多个错误描述,异步数据验证以及在错误状态改变时通知view的功能。然而,INotifyDataError当前只在Silverlight4中支持,WPF4尚不支持。

public abstract class DomainObject : INotifyPropertyChanged,INotifyDataErrorInfo{private ErrorsContainer<ValidationResult> errorsContainer =new ErrorsContainer<ValidationResult>(pn => this.RaiseErrorsChanged( pn ) );public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;public bool HasErrors{get { return this.ErrorsContainer.HasErrors; }}public IEnumerable GetErrors( string propertyName ){return this.errorsContainer.GetErrors( propertyName );}protected void RaiseErrorsChanged( string propertyName ){var handler = this.ErrorsChanged;if (handler != null){handler(this, new DataErrorsChangedEventArgs(propertyName) );}}...}




原创粉丝点击