Prism应用开发(五)——MVVM模式关键技术
2016-08-12 09:13
621 查看
一、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接口的对象,例如:
[csharp]
view plain
copy
print?
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; }
}
[html]
view plain
copy
print?
<Button Command="{Binding Path=SubmitCommand}" CommandParameter="SubmitOrder"/>
[html]
view plain
copy
print?
<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的索引器属性将会在第一次数据绑定或者属性的每次改变被调用,因为索引器属性在每个属性发生改变的时候都会被调用,所以要保证这个数据验证函数要尽可能的高效。
[html]
view plain
copy
print?
<TextBox
Text="{Binding Path=CurrentEmployee.Name, Mode=TwoWay, ValidatesOnDataErrors=True,
NotifyOnValidationError=True }"
/>
[csharp]
view plain
copy
print?
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
}
[csharp]
view plain
copy
print?
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) );
}
}
...
}
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接口的对象,例如:
[csharp]
view plain
copy
print?
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; }
}
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; } }
[html]
view plain
copy
print?
<Button Command="{Binding Path=SubmitCommand}" CommandParameter="SubmitOrder"/>
<Button Command="{Binding Path=SubmitCommand}" CommandParameter="SubmitOrder"/>
[html]
view plain
copy
print?
<Button Content="Submit" IsEnabled="{Binding CanSubmit}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding SubmitCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<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的索引器属性将会在第一次数据绑定或者属性的每次改变被调用,因为索引器属性在每个属性发生改变的时候都会被调用,所以要保证这个数据验证函数要尽可能的高效。
[html]
view plain
copy
print?
<TextBox
Text="{Binding Path=CurrentEmployee.Name, Mode=TwoWay, ValidatesOnDataErrors=True,
NotifyOnValidationError=True }"
/>
<TextBox Text="{Binding Path=CurrentEmployee.Name, Mode=TwoWay, ValidatesOnDataErrors=True, NotifyOnValidationError=True }" />
[csharp]
view plain
copy
print?
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
}
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尚不支持。
[csharp]
view plain
copy
print?
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) );
}
}
...
}
相关文章推荐
- Prism应用开发(四)——MVVM模式基础
- Prism应用开发(四)——MVVM模式基础
- 嵌入式关键技术分析与开发应用
- 嵌入式系统关键技术分析与开发应用[163 BLOG]
- [转载]当今计算机软件开发和应用领域最重要十种关键技术
- Soap技术在Windows应用程序开发中的应用B/S与C/S混合模式开发[草稿]
- 插件开发技术说明(17)---应用CRUD开发模式范例
- 通用Windows应用《博客园-开发者的网上家园》开发(1)——MVVM模式
- 当今计算机软件开发和应用领域最重要十种关键技术排名
- silverlight 学习笔记 (九):Prism与MVVM模式在silverlight中的应用
- 【转】嵌入式系统关键技术分析与开发应用
- 企业应用开发模式 ERP项目中应用到的技术和工具
- 嵌入式系统关键技术分析与开发应用
- 当今计算机软件开发和应用领域最重要十种关键技术排名
- Prism应用开发(六)——MVVM高级话题
- Prism应用开发(六)——MVVM高级话题
- 企业应用开发模式 ERP项目中应用到的技术和工具
- COM与基于组件技术的开发和应用模式(一)
- Soap技术在Windows应用程序开发中的应用B/S与C/S混合模式开发[草稿]
- Asp.net20 应用之 基于AJAX.NET技术的DataGrid控件开发