开发手册 欢迎您!
软件开发者资料库

MVVM - 验证

MVVM验证 - 从简单和简单的步骤学习MVVM,从基本到高级概念,包括简介,优势,责任,第一个应用程序,连接视图,连接ViewModel,WPF数据绑定,WPF数据模板,View和ViewModel通信,层次结构和导航,验证,依赖注入,事件,单元测试,框架,面试问题。

在本章中,我们将了解验证.我们还将看一个干净的方法来验证WPF绑定已经支持但是将它绑定到MVVM组件.

MVVM中的验证

  • 当您的应用程序开始接受最终用户的数据输入时,您需要考虑验证该输入.

  • 确保它符合您的总体要求.

  • WPF在绑定系统中有一些很棒的构建和功能,用于验证输入,您仍然可以利用所有这些功能.做MVVM.

  • 请记住支持验证的逻辑,并定义哪些属性应该是Model或ViewModel的一部分,而不是视图本身.

您仍然可以使用WPF数据绑定支持的所有表达验证方式,包括 :

  • 设置属性上的抛出异常.

  • 实现IDataErrorI nfo接口.

  • 实现INotifyDataErrorInfo.

  • 使用WPF验证规则.

一般情况下,建议使用INotifyDataErrorInfo并将其引入WPF .net 4.5,它支持查询对象以查找与属性相关的错误,并且还修复了所有其他选项的一些缺陷.具体来说,它允许异步验证.它允许属性有多个与之关联的错误.

添加验证

让我们来看一个我们将添加验证的示例支持我们的输入视图,在大型应用程序中,您可能需要在应用程序中的许多位置.有时在View上,有时在ViewModel上,有时在这些辅助对象上有模型对象周围的包装.

将验证支持放在一个公共基类中是一个很好的做法,然后你可以继承它来自不同场景.

基类将支持INotifyDataErrorInfo,以便在属性更改时触发该验证.

创建添加一个名为ValidatableBindableBase的新类.由于我们已经有了一个属性更改处理的基类,让我们从中派生基类并实现INotifyDataErrorInfo接口.

以下是ValidatableBindableBase类的实现.

using System; using System.Collections.Generic; using System.ComponentModel; //using System.ComponentModel.DataAnnotations; using System.Linq; using System.Runtime.CompilerServices; using System.Text;using System.Threading.Tasks; using System.Windows.Controls;namespace MVVMHierarchiesDemo {    public class ValidatableBindableBase : BindableBase, INotifyDataErrorInfo {       private Dictionary> _errors = new Dictionary>();      public event EventHandler          ErrorsChanged = delegate { };      public System.Collections.IEnumerable GetErrors(string propertyName) {         if (_errors.ContainsKey(propertyName))             return _errors[propertyName];          else             return null;       }            public bool HasErrors {          get { return _errors.Count > 0; }       }      protected override void SetProperty(ref T member, T val,          [CallerMemberName] string propertyName = null) {         base.SetProperty(ref member, val, propertyName);         ValidateProperty(propertyName, val);      }      private void ValidateProperty(string propertyName, T value) {         var results = new List();         //ValidationContext context = new ValidationContext(this);          //context.MemberName = propertyName;         //Validator.TryValidateProperty(value, context, results);         if (results.Any()) {            //_errors[propertyName] = results.Select(c => c.ErrorMessage).ToList();          } else {             _errors.Remove(propertyName);          }         ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));       }    }  }

现在在相应的文件夹中添加AddEditCustomerView和AddEditCustomerViewModel.以下是AddEditCustomerView.xaml的代码.

                                                                                                                                                                                                                                                                                            

以下是AddEditCustomerViewModel实现.

using MVVMHierarchiesDemo.Model;using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace MVVMHierarchiesDemo.ViewModel {    class AddEditCustomerViewModel : BindableBase {       public AddEditCustomerViewModel() {         CancelCommand = new MyIcommand(OnCancel);          SaveCommand = new MyIcommand(OnSave, CanSave);       }       private bool _EditMode;       public bool EditMode {          get { return _EditMode; }          set { SetProperty(ref _EditMode, value);}       }      private SimpleEditableCustomer _Customer;      public SimpleEditableCustomer Customer {          get { return _Customer; }          set { SetProperty(ref _Customer, value);}       }      private Customer _editingCustomer = null;      public void SetCustomer(Customer cust) {         _editingCustomer = cust;          if (Customer != null) Customer.ErrorsChanged -= RaiseCanExecuteChanged;          Customer = new SimpleEditableCustomer();         Customer.ErrorsChanged += RaiseCanExecuteChanged;         CopyCustomer(cust, Customer);       }      private void RaiseCanExecuteChanged(object sender, EventArgs e) {          SaveCommand.RaiseCanExecuteChanged();       }      public MyIcommand CancelCommand { get; private set; }      public MyIcommand SaveCommand { get; private set; }      public event Action Done = delegate { };      private void OnCancel() {          Done();       }      private async void OnSave() {          Done();       }      private bool CanSave() {          return !Customer.HasErrors;       }     } }

以下是SimpleEditableCustomer类的实现.

using System;using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace MVVMHierarchiesDemo.Model {    public class SimpleEditableCustomer : ValidatableBindableBase {       private Guid _id;       public Guid Id {          get { return _id; }          set { SetProperty(ref _id, value); }       }      private string _firstName;       [Required]      public string FirstName {          get { return _firstName; }          set { SetProperty(ref _firstName, value); }       }      private string _lastName;       [Required]       public string LastName {           get { return _lastName; }          set { SetProperty(ref _lastName, value); }       }      private string _email;       [EmailAddress]       public string Email {         get { return _email; }          set { SetProperty(ref _email, value); }       }      private string _phone;       [Phone]       public string Phone {          get { return _phone; }          set { SetProperty(ref _phone, value); }       }    } }

编译并执行上述代码时,您将看到以下窗口.

MVVM Validations MainWindow1

当您按添加客户按钮时,您将请参阅以下视图.当用户将任何字段留空时,它将突出显示并且保存按钮将被禁用.

MVVM验证MainWindow2