使用 WCF RIA 和 MVVM 模式验证 UI 上的数据
是否存在使用 MVVM 与 Silverlight 中的 RIA 服务结合构建和验证数据的最佳实践或广泛接受的方法?
这是我的问题的症结所在。假设我有一个 EmployeeView、EmployeeViewModel 和一些 Employee 实体。在常规 RIA 应用程序中,我将在视图上公开 Employee 实体,并且“免费”获得验证,因为实体实现了 INotifyDataErrorInfo 和 IDataErrorInfo(正确吗?)。
现在,如果我想通过 ViewModel 而不是直接通过实体公开一些 Employee 属性,那么它会变得更加复杂。我可以直接公开我需要的位并将它们挂接到后端的实体中,如下所示:
private Employee _employee;
public EmployeeViewModel()
{
_employee = new Employee();
}
public string Name
{
get { return _employee.Name; }
set
{
_employee.Name = value;
// fire property change, etc.
}
}
...但我失去了实体的美味“免费”验证。否则,我可以直接在视图模型中公开实体,就像这样
private Employee _employee;
public Employee Employee
{
get { return _employee; }
}
public EmployeeViewModel()
{
_employee = new Employee();
}
在这种情况下,视图将直接绑定到 Employee 实体并在其中找到它的属性,如下所示:
<StackPanel DataContext="{Binding Employee}">
<TextBox Text="{Binding Name}" />
</StackPanel>
使用此方法我们可以获得“免费”验证,但它是不完全是 MVVM 的干净实现。
第三种选择是在虚拟机中自己实现 INotifyDataErrorInfo 和 IDataErrorInfo ,但这看起来像是大量的管道代码,考虑到我使用上述解决方案是多么容易,并且有一些稍微不太“干净”但很糟糕的东西归根结底,事情变得容易多了。
所以我想我的问题是,这些方法中哪种适合哪种情况?我缺少更好的方法吗?
如果它是相关的,我正在查看 Caliburn.Micro MVVM 框架,但我很想看到普遍适用的答案。
Is there a best practice or widely accepted way of structuring and validating data using MVVM in conjunction with RIA services in Silverlight?
Here's the crux of my problem. Let's say I have an EmployeeView, EmployeeViewModel and some Employee entity. In regular RIA applications I will expose that Employee entity on the view and I get validation "for free", because Entities implement INotifyDataErrorInfo and IDataErrorInfo (correct?).
Now if I want to expose some Employee properties through a ViewModel instead of directly through an Entity then it becomes more complicated. I could expose the bits that I need directly and hook them into the entity on the backend, like this:
private Employee _employee;
public EmployeeViewModel()
{
_employee = new Employee();
}
public string Name
{
get { return _employee.Name; }
set
{
_employee.Name = value;
// fire property change, etc.
}
}
... but I lose the tasty "free" validation of entities. Otherwise, I could expose the entity directly in the view model, like so
private Employee _employee;
public Employee Employee
{
get { return _employee; }
}
public EmployeeViewModel()
{
_employee = new Employee();
}
In this case, the view will bind directly to the Employee entity and find its properties in there, like so:
<StackPanel DataContext="{Binding Employee}">
<TextBox Text="{Binding Name}" />
</StackPanel>
Using this method we get "free" validation, but it's not exactly a clean implementation of MVVM.
A third option would be to implement INotifyDataErrorInfo and IDataErrorInfo myself in the VMs, but this seems like an awful lot of plumbing code, considering how easy it would be for me to use the above solution and have something slightly less "clean" but a heck of a lot easier at the end of the day.
So I guess my question is, which of these approaches are appropriate in which situation? Is there a better approach I am missing?
In case it's relevant I'm looking at the Caliburn.Micro MVVM framework, but I would be keen to see answers that apply generically.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我正在将 RIA 与 Caliburn.Micro 结合使用,并且对我的客户端验证解决方案非常满意。
我所做的是将
ValidationBaseViewModel
放在Screen
(由 Caliburn.Micro 提供)和我的实际应用程序 VM(在您的情况下是EmployeeViewModel
)之间。ValidationBaseViewModel
实现了INotifyDataErrorInfo
,以便您谈论的管道代码只编写一次。然后,我通过ValidationBaseViewModel
从 (Caliburn.Micro)PropertyChangedBase.NotifyOfPropertyChange
的覆盖添加/删除/通知错误,代码如下:这实际上是在另一个虚拟机中( ValidationBaseViewModel 和 EmployeeViewModel 之间),具有以下定义:
其中
Entity
是 RIASystem.ServiceModel.DomainServices.Client.Entity
,_editing
类成员是当前虚拟机正在编辑的此类型TEdit
的实例。与 Caliburn 协程结合使用,我可以做一些很酷的事情,如下所示:
I am using RIA with Caliburn.Micro and am pretty happy with my solution for client side validation.
What I have done is put a
ValidationBaseViewModel
betweenScreen
(provided by Caliburn.Micro) and my actual application VMs (EmployeeViewModel
in your case).ValidationBaseViewModel
implementsINotifyDataErrorInfo
so that plumbing code your talking about is only written once. I then add/remove/notify of errors viaValidationBaseViewModel
from an override of the (Caliburn.Micro)PropertyChangedBase.NotifyOfPropertyChange
with the following code:This is actually in another VM (between ValidationBaseViewModel and EmployeeViewModel) with the following definition:
where
Entity
is RIAsSystem.ServiceModel.DomainServices.Client.Entity
and the_editing
class member is an instance of this typeTEdit
which is being edited by the current VM.In combination with Caliburn coroutines this allows me to do some cool stuff like the following:
如果您不想使用外部资源或框架,那么我可以有一个实现
INotifyDataErrorInfo
的ViewModelBase
。该类将使用 ValidateProperty(string propertyName, object value) 来验证特定属性,并使用 Validate() 方法来验证整个对象。内部使用
验证器
类返回ValidationResult
。如果您使用反射器,则可以通过模仿
Entity
类本身到ViewModelBase
。虽然它不是“免费”,但仍然相对便宜。
以下是
IDataErrorInfo
的示例实现。虽然没有经过测试,但会给你这个想法。If you don't want to use external resources or frameworks, then I you could have a
ViewModelBase
that implementINotifyDataErrorInfo
.That class will have
ValidateProperty(string propertyName, object value)
to validate a speciic property, andValidate()
method to validate the entire object. Internally use theValidator
class to return theValidationResult
s.If you use reflector, it can be pretty easy to achieve by mimicking the validation process in the
Entity
class itself to theViewModelBase
.Although it's no "free", is still relatively cheap tho.
Here is a sample implementation of
IDataErrorInfo
. Although not tested, will give you the idea.您可以使用分部类来扩展您的实体并通过 idataerrorinfo 添加数据验证。
you can use a partial class to extend your entitty and add data validation there via idataerrorinfo.