[Silverlight入门系列]使用MVVM模式(5):异步Validation数据验证和INotifyDataErrorInfo接口
- 博客分类:
- MVVM
数据验证(Validation)是界面程序的常见需求,例如使用正则表达式验证用户输入的Email地址是否合法,然后在界面给出错误提示信息。在Sivlerlight的MVVM模式中,我们在Model和ViewModel可以做Validation,然后需要把Model和ViewModel的Validation结果和错误信息通知视图(View)。在WPF中,我们使用IDataErrorInfo,在Silverlight4中,建议使用INotifyDataErrorInfo。
IDataErrorInfo
先简单说一下IDataErrorInfo,这个接口实现了简单的数据验证和错误报告功能,只能说聊胜于无吧。例子:
1 <TextBox Text="{Binding Path=CurrentEmployee.Name, Mode=TwoWay, ValidatesOnDataErrors=True, NotifyOnValidationError=True }" />
INotifyDataErrorInfo
这个接口只有Silverlight4以上支持,非常强大,支持一个绑定属性多重错误、异步数据验证、自动通知视图错误信息、ErrorChanged事件、HasErrors属性、GetErrors方法等等。定义:
1 public interface INotifyDataErrorInfo 2 { 3 bool HasErrors { get; } 4 5 event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged; 6 7 IEnumerable GetErrors(string propertyName); 8 }
实现这个INotifyDataErrorInfo接口也非常简单,来个简单的例子:
1 public class SimpleModel : INotifyDataErrorInfo 2 { 3 public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged; 4 5 private Dictionary<string, List<String>> _errors = new Dictionary<string, List<String>>(); 6 7 private string _accountID = null; 8 9 public string AccountID 10 { 11 get { return _accountID; } 12 set 13 { 14 if (_accountID != value) 15 { 16 var propertyName = "AccountID"; 17 18 if (string.IsNullOrEmpty(value)) 19 { 20 if (!_errors.ContainsKey(propertyName)) 21 _errors.Add(propertyName, new List<string>()); 22 23 _errors[propertyName].Add("AccountID can't be null or empty"); 24 } 25 else 26 { 27 if (_errors.ContainsKey(propertyName)) 28 _errors.Remove(propertyName); 29 } 30 31 NotifyErrorsChanged(propertyName); 32 33 //Maybe you don't want to set this field to a value if the validation fails 34 _accountID = value; 35 } 36 } 37 38 } 39 40 public System.Collections.IEnumerable GetErrors(string propertyName) 41 { 42 if (_errors.ContainsKey(propertyName)) 43 return _errors[propertyName]; 44 45 return _errors.Values; 46 } 47 48 public bool HasErrors 49 { 50 get { return _errors.Count > 0; } 51 } 52 53 54 private void NotifyErrorsChanged(string propertyName) 55 { 56 if (ErrorsChanged != null) 57 ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName)); 58 } 59 }
异步Validation数据验证和INotifyDataErrorInfo接口
这个例子稍微复杂,实现了异步调用WCF RIA Service进行业务逻辑的validation并在ViewModel中把验证的错误提示通知视图,完整的代码下载,需要VS2010和Silverlight环境。
代码说明 ViewModel基类:
1 using System; 2 using System.Net; 3 using System.Windows; 4 using System.Linq; 5 using System.Windows.Controls; 6 using System.Windows.Documents; 7 using System.Windows.Ink; 8 using System.Windows.Input; 9 using System.Windows.Media; 10 using System.Windows.Media.Animation; 11 using System.Windows.Shapes; 12 using System.ComponentModel; 13 using System.Collections.Generic; 14 using System.Collections; 15 16 namespace AsycValidation 17 { 18 public class BasicViewModel : INotifyPropertyChanged, INotifyDataErrorInfo 19 { 20 public event PropertyChangedEventHandler PropertyChanged; 21 public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged; 22 23 24 private Dictionary<string, List<ValidationErrorInfo>> _errors = 25 new Dictionary<string, List<ValidationErrorInfo>>(); 26 27 28 protected void RemoveErrorFromPropertyAndNotifyErrorChanges( 29 string propertyName, 30 int errorCode) 31 { 32 if (_errors.ContainsKey(propertyName)) 33 { 34 RemoveErrorFromPropertyIfErrorCodeAlreadyExist(propertyName, errorCode); 35 36 NotifyErrorsChanged(propertyName); 37 } 38 } 39 40 private void RemoveErrorFromPropertyIfErrorCodeAlreadyExist( 41 string propertyName, 42 int errorCode) 43 { 44 if (_errors.ContainsKey(propertyName)) 45 { 46 var errorToRemove = _errors[propertyName].SingleOrDefault( 47 error => error.ErrorCode == errorCode); 48 49 if (errorToRemove != null) 50 { 51 _errors[propertyName].Remove(errorToRemove); 52 53 54 55 56 if (_errors[propertyName].Count == 0) 57 _errors.Remove(propertyName); 58 } 59 } 60 } 61 protected void AddErrorToPropertyAndNotifyErrorChanges( 62 string propertyName, 63 ValidationErrorInfo errorInfo) 64 { 65 RemoveErrorFromPropertyIfErrorCodeAlreadyExist(propertyName, errorInfo.ErrorCode); 66 if (!_errors.ContainsKey(propertyName)) 67 _errors.Add(propertyName, new List<ValidationErrorInfo>()); 68 69 _errors[propertyName].Add(errorInfo); 70 71 NotifyErrorsChanged(propertyName); 72 } 73 74 75 public IEnumerable GetErrors(string propertyName) 76 { 77 if (!_errors.ContainsKey(propertyName)) 78 return _errors.Values; 79 80 return _errors[propertyName]; 81 } 82 83 84 public bool HasErrors 85 { 86 get { return this._errors.Count > 0; } 87 } 88 89 90 private void NotifyErrorsChanged(string propertyName) 91 { 92 if (ErrorsChanged != null) 93 ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName)); 94 } 95 96 97 protected void NotifyPropertyChanged(string propertyName) 98 { 99 if (PropertyChanged != null) 100 PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 101 } 102 103 } 104 }
Model:
1 using System; 2 using System.Net; 3 using System.Windows; 4 using System.Windows.Controls; 5 using System.Windows.Documents; 6 using System.Windows.Ink; 7 using System.Windows.Input; 8 using System.Windows.Media; 9 using System.Windows.Media.Animation; 10 using System.Windows.Shapes; 11 using System.ComponentModel; 12 13 namespace AsycValidation 14 { 15 public class CompanyModel : INotifyPropertyChanged 16 { 17 public event PropertyChangedEventHandler PropertyChanged; 18 19 public int CompanyID { get; set; } 20 21 private string _CompanyName; 22 public string CompanyName 23 { 24 get { return _CompanyName; } 25 set 26 { 27 _CompanyName = value; 28 29 if (PropertyChanged != null) 30 { 31 PropertyChanged(this, new PropertyChangedEventArgs("CompanyName")); 32 } 33 } 34 } 35 } 36 }
ViewModel,继承了BaseViewModel基类:
1 using System; 2 using System.Net; 3 using System.Windows; 4 using System.Windows.Controls; 5 using System.Windows.Documents; 6 using System.Windows.Ink; 7 using System.Windows.Input; 8 using System.Windows.Media; 9 using System.Windows.Media.Animation; 10 using System.Windows.Shapes; 11 using AsycValidation.Web; 12 13 namespace AsycValidation 14 { 15 public class CompanyViewModel : BasicViewModel 16 { 17 public CompanyModel CompanyModelData { get; set; } 18 19 public CompanyViewModel(CompanyModel model) 20 { 21 CompanyModelData = model; 22 } 23 24 private string _CompanyName = null; 25 private const int ACCOUNT_ALREADY_EXIST_ERROCODE = 100; 26 27 DomainService1 service = new DomainService1(); 28 29 public string CompanyName 30 { 31 get 32 { 33 return _CompanyName; 34 } 35 set 36 { 37 if (_CompanyName != value) 38 { 39 var propertyName = "CompanyName"; 40 41 ValidateAccountAlreadyExists( 42 value, 43 propertyName, 44 ACCOUNT_ALREADY_EXIST_ERROCODE, 45 string.Format("Company with the ID {0} already exists", value)); 46 47 _CompanyName = value; 48 NotifyPropertyChanged(propertyName); 49 } 50 } 51 } 52 53 private void ValidateAccountAlreadyExists( 54 string CompanyID, 55 string propertyName, 56 int errorCode, 57 string errorMsg) 58 { 59 service.DoesCompanyExists( 60 CompanyID, 61 invokeOperation => 62 { 63 if (invokeOperation.Value) 64 { 65 AddErrorToPropertyAndNotifyErrorChanges( 66 propertyName, 67 new ValidationErrorInfo() 68 { 69 ErrorCode = errorCode, 70 ErrorMessage = errorMsg 71 }); 72 } 73 else 74 { 75 RemoveErrorFromPropertyAndNotifyErrorChanges( 76 propertyName, 77 errorCode); 78 } 79 }, 80 null); 81 } 82 83 } 84 }
View / XAML
1 <UserControl x:Class="AsycValidation.MainPage" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:wm="clr-namespace:AsycValidation" 7 mc:Ignorablecolor: #0000f发表评论
-
[Silverlight入门系列]使用MVVM模式(7):ViewModel的INotifyPropertyChanged接口实现
2011-06-06 20:44 1458上一篇说到《Model的INotifyPropertyCh ... -
[Silverlight入门系列]使用MVVM模式(6):使用Behavior
2011-06-06 20:42 1648Behavior把一些常用的行为封装成可重复使用的组件(C ... -
[Silverlight入门系列]使用MVVM模式(4):Prism的NotificationObject自动实现INotifyPropertyChanged接
2011-06-06 20:37 1416在上一篇写了Model的INotifyPropertyChan ... -
[Silverlight入门系列]使用MVVM模式(3):Model的INotifyPropertyChanged接口实现
2011-06-06 20:36 985当客户端绑定一个数据模型以后,数据模型变化以后可以自动通知 ... -
[Silverlight入门系列]使用MVVM模式(2):集合
2011-06-06 20:33 1178Model /ObservableCollection/ICo ... -
[Silverlight入门系列]使用MVVM模式(1):MVVM核心概念
2011-06-06 20:26 1620MVVM模式是Model、View、ViewModel的简称, ...
相关推荐
在Silverlight应用开发中,MVVM(Model-View-ViewModel)模式是一种常用的设计模式,它将业务逻辑、用户界面和数据模型分离,提高了代码的可测试性和可维护性。本篇将深入探讨在Silverlight中如何在MVVM模式下进行...
在Silverlight中,MVVM能够帮助开发者将业务逻辑、用户界面和数据模型分离,从而提高代码的可测试性和可扩展性。 首先,我们来了解Silverlight。Silverlight是微软推出的一种插件技术,用于在Web浏览器中实现丰富的...
MVVM(Model-View-ViewModel)模式是Silverlight开发中的一个重要设计模式,它通过将用户界面(View)、业务逻辑(ViewModel)和数据模型(Model)分离,实现了高可测试性、可维护性和可扩展性的代码结构。...
在Windows Presentation Foundation (WPF) 中,MVVM(Model-View-ViewModel)是一种设计模式,它将业务逻辑、用户界面和数据模型分离,使得代码更易于维护和测试。本篇文章将详细探讨如何在MVVM模式下有效地使用...
在Silverlight中,有一些库如Caliburn.Micro、Prism和MVVM Light等,它们提供了对MVVM模式的良好支持,包括依赖注入、事件代理、路由和导航等功能,帮助开发者更方便地实现MVVM架构。 综上所述,"Silverlight MVVM...
WPF和Silverlight框架提供了丰富的数据绑定支持,这使得MVVM模式能够充分发挥其优势。数据绑定允许UI元素自动更新以反映数据模型的变化,而无需编写大量的手动更新代码。此外,WPF和Silverlight的XAML标记语言使得...
在 Silverlight 应用开发中,MVVM(Model-View-ViewModel)模式是一种常见的设计模式,它将应用程序的用户界面(View)、业务逻辑(ViewModel)和数据模型(Model)分离,提高了代码的可测试性和可维护性。...
综上所述,这个"silverlight自定义日历"项目展示了如何利用MVVM模式和Silverlight技术来构建一个灵活且可扩展的UI组件。通过模型处理数据,视图模型提供用户交互逻辑,视图则呈现美观的用户界面,实现了自定义日历的...
"使用Command机制实现的Silverlight4.0多层MVVM模式简单案例"是一个适合初学者学习的示例,它演示了如何在Silverlight中应用MVVM模式来构建一个分层的、可维护的UI。通过了解并实践这个案例,开发者可以掌握MVVM的...
WPF提供了内置的数据验证机制,例如使用`IDataErrorInfo`接口或者`ValidationRule`类。框架可能已经封装了这些验证机制,方便开发者在ViewModel中轻松实现数据验证规则。 **WpfFormsWithValidationDemo** 这个...
在Silverlight应用中,MVVM(Model-View-ViewModel)是一种设计模式,它提倡将业务逻辑、用户界面和数据模型分离,从而实现更清晰的代码结构和更好的可测试性。以下是对MVVM模式在Silverlight中的应用进行的详细说明...
MVVM 模式下的 SilverLight 基于 MySQL 数据库的实例解析 在SilverLight应用程序开发中,MVVM(Model-View-ViewModel)是一种常见的开发模式,它是MVC模式的一种变种。MVVM 模式将整个应用程序分为三个模块,即 ...
**Silverlight探秘系列课程(1):创建第一个Silverlight应用** Silverlight是微软推出的一种基于浏览器的插件技术,用于构建丰富的、交互式的Web应用程序。这个系列课程旨在引导学习者深入了解Silverlight,并通过...
- `INotifyDataErrorInfo`:这是.NET Framework 4.5引入的新接口,提供异步验证和多属性依赖验证的能力,更适应复杂的验证场景。它包含多个事件和方法,如`HasErrors`属性、`GetErrors`方法以及`ErrorsChanged`事件...
"MVVM in Delphi: Architecting and Building Model View ViewModel Applications" 2016 | ISBN-10: 148422213X | 143 pages | PDF, EPUB | 23 MB Dive into the world of MVVM, learn how to build modern ...
在"Silverlight MVVM 窗体数据传递"的场景中,我们关注的是如何在父窗体和子窗体之间进行数据交换: 1. **父窗体**:通常包含一个按钮,用户点击后会触发打开子窗体的逻辑。在MVVM模式下,这个按钮通常绑定到...
WPF自制TextBox利用Validation验证来实现必填项和焦点的提示特效。 此为专门为MVVM模式的实现。网上要么搜不到真实可用的,要么就是一大堆看不懂的机制绕路太远。我写了个简单明了的。希望可以帮助大家更好地利用...
MVVM(Model-View-ViewModel)模式是一种设计模式,尤其在开发富客户端应用程序时非常流行,如Silverlight。这种模式将应用程序分为三个主要组件:模型(Model)、视图(View)和视图模型(ViewModel)。MVVM的核心...