Silverlight MVVM 和通过 WCF 进行验证






4.18/5 (4投票s)
Silverlight WCF 启用项目的输入验证示例

引言
本文介绍如何在简单的 POCO(普通 CLR 对象)中添加和启用验证逻辑,以及 Silverlight 客户端如何通过 WCF 数据服务使用它们。
背景
我写这篇文章是因为在 Silverlight .NET 中创建一个简单的验证测试项目时,应用于我的模型的验证规则没有在 WCF 服务的消费者端(在本例中,是 Silverlight 客户端)触发。我想知道为什么当我的 WCF 数据服务被客户端使用时,这些规则没有被触发,并得出结论:客户端上由代理创建的引用模型类不包含我添加到模型类中的验证属性。本文向您展示了解决此问题的一种可能方案。
架构
示例应用程序代表典型的 MVVM(模型-视图-视图模型)架构。我将简要解释嵌入在解决方案中的不同项目。
MVVM_Base
: 基础 ViewModel 项目,它公开了一些用于启用 MVVM 架构和验证的类。MVVM_DataService
: 公开可由客户端使用的 WCF 服务。MVVM_Model_SL
: Silverlight 类库,其中包含我们的模型类。MVVM_MyValidation
: Silverlight 客户端应用程序。MVVM_MyValidation.Web
: 托管网站。
![]() |
深入解释 MVVM 模式超出了本文的范围。因此,读者应该熟悉基本的 MVVM 概念。 |
模型
我保持模型非常简单,只包含两个带有简单属性验证的属性。验证触发逻辑封装在 ValidatingViewModelBase
类中,它是 MVVM 基础项目的一部分。
public class Employee : ValidatingViewModelBase
{
private string _firstName;
[Required(ErrorMessage="Firstname is required!")]
public string FirstName
{
get { return _firstName; }
set { _firstName = value; OnPropertyChanged("FirstName"); }
}
private string _lastName;
[Required(ErrorMessage = "Lastname is required!")]
public string LastName
{
get { return _lastName; }
set { _lastName = value; OnPropertyChanged("LastName"); }
}
}
![]() |
如果你查看 MVVM_Model_SL 项目的代码(在 zip 文件中提供),你会注意到我添加了 MVVM 基类的链接。 我不得不这样做,因为我将 MVVM_Base 项目实现为一个普通的类库(而不是一个特定的 Silverlight 类库),所以我可以在其他项目中重用我的 MVVM 实现。添加链接是必要的,因为你不能在 Silverlight 类库项目中引用一个普通的类库。 |
数据服务
- 该服务是一个 WCF 服务,它实现了
IEmployeeService
并公开了方法GetEmployees
。 - 实现类返回一个员工对象列表。
using MVVM_Model_SL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace MVVM_DataService
{
[ServiceContract]
public interface IEmployeeService
{
[OperationContract]
List<employee /> GetEmployees();
}
}
using MVVM_Model_SL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace MVVM_DataService
{
public class EmployeeService : IEmployeeService
{
public List<employee /> GetEmployees()
{
return
new List<employee />(){
new Employee{FirstName="Marc",LastName="Spencer"},
new Employee{FirstName="Julie",LastName="Matthews"};
}
}
}
ViewModel
ViewModel
是我们的 Silverlight 应用程序的一部分,它是 View 和我们的 WCF 数据服务之间的桥梁。- View 通过
ViewModel
进行通信并获取其数据。 ViewModel
中的代码非常不言自明。
namespace MVVM_MyValidation.ViewModels
{
public class EmployeeViewModel : MVVM_Base.ValidatingViewModelBase
{
#region Storage
// Instance of the Service Client
private EmployeeServiceClient _serviceClient;
// Holds the returned employees as an Observable Collection
private ObservableCollection<employee /> _employeeList;
public ObservableCollection<employee /> EmployeeList
{
get { return _employeeList; }
set { _employeeList = value; OnPropertyChanged("EmployeeList"); }
}
#endregion Storage
#region Ctor
public EmployeeViewModel()
{
// Create the Service client a get the employees
_serviceClient = new EmployeeServiceClient();
RefreshEmployees();
}
#endregion Ctor
#region Public Interface
// Get the Number of Employees in the Collection
public Int32 NumberOfEmployees
{
get { return _employeeList.Count; }
}
// Set/Get the Current Employee
private Employee _currentEmployee;
public Employee CurrentEmployee
{
get { return _currentEmployee; }
set { _currentEmployee = value; OnPropertyChanged("CurrentEmployee"); }
}
#endregion Public Interface
#region Private Interface
// Get the Employee List from the Service &
// point to the first employee. This is done in an Async Way.
private void RefreshEmployees()
{
_serviceClient.GetEmployeesCompleted += (s, e) =>
{
EmployeeList = e.Result;
CurrentEmployee = EmployeeList.Count > 0 ? EmployeeList[0] : null;
};
_serviceClient.GetEmployeesAsync();
}
#endregion Private Interface
}
}
View
- View 是 Silverlight 应用程序的一部分。
- View 将其
DataContext
设置为ViewModel
。
namespace MVVM_MyValidation.Views
{
public partial class EmployeeView : Page
{
private EmployeeViewModel _viewModel;
public EmployeeView()
{
InitializeComponent();
_viewModel = new EmployeeViewModel();
Loaded += (s, e) =>
{
DataContext = _viewModel;
};
}
// Executes when the user navigates to this page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
}
}
一旦 DataContext
被设置,View 就可以通过 .NET 中的 databinding
功能轻松地绑定到它的属性。下面的代码片段突出显示并记录了最重要的部分

DataGrid
绑定到我们的ViewModel
公开的EmployeeList
。DataColumns
绑定到Employee
公开的属性。CurrentEmployee
保存对DataGrid
中当前选定的Employee
的引用。TextBoxes
绑定到CurrentEmployee
的属性。
我们的 View 绑定中最有趣的部分是详细信息列,它允许用户修改当前 Employee
属性的内容。事实上,验证异常在绑定的属性上被激活(通过 ValidatesOnDataErrors
和 ValidatesOnExceptions
属性)。 奇怪的是,除非你显式地将模型作为引用添加到项目,并将服务引用配置为重用所有引用程序集中的类型,否则验证将不会被触发。原因是引用的生成的代理代码不包含客户端的验证代码。因此,你必须以某种方式“绕过”这个生成的类,方法是将原始模型类作为引用添加到客户端项目,并确保服务代理引用被配置为重用所有引用程序集中的所有类型。这样,GUI 将绑定到模型类而不是生成的代理类。由于原始模型类包含验证属性,因此将发生数据验证。实现此目的的配置步骤如下所示
*步骤 1:将模型作为引用添加到客户端项目
*步骤 2:配置服务引用以重用所有引用程序集中的类型
就这样,各位!